// import TTable, { TTd ,TTh, TTr } from 't/basic/table';
import TTable from 't/basic/table';
import TTr from 't/basic/table/Tr';
import TTd from 't/basic/table/Td';
import TTh from 't/basic/table/Th';
import TCheckbox from 't/basic/checkbox';
import TRadio from 't/basic/radio';
import TBtn from 't/basic/button';
import TIcon from 't/basic/icon';
import TCard from 't/basic/card';
import TMenu from 't/basic/menu';
import TList from 't/basic/list';
import TItem from 't/basic/item';
import TItemSection from 't/basic/item-section';
import QDialog from '@teld/q-components/Dialog';
// import NoDataPlaceholder from 't/basic/import-export/components/no-data-placeholder.vue';
import NoDataPlaceholder from './components/no-data-placeholder.vue';
import NoData from 't/bussiness/repeat/no-data.vue';
import QInnerLoading from '@teld/q-components/InnerLoading';
import QResizeObserver from '@teld/q-components/ResizeObserver';
import QIntersection from '@teld/q-components/Intersection';
// import QPagination from '@teld/q-components/Pagination';
import TPagination from 't/basic/pagination';
import TPrefabPagination, { C_Prefab } from 't/bussiness/prefab-pagination';

import TInput from 't/basic/input';

import useMappingProps from 't/common/hooks/useMappingProps';
import {
  commonProps,
  pickOwnForBasicComponent,
  usePropsTwoWayValues,
  zipFasDynamicFilter,
  filter2FasDynamicFilter,
} from 't/common/utils';
import {
  computed,
  defineComponent,
  getCurrentInstance,
  nextTick,
  onMounted,
  onUnmounted,
  reactive,
  ref,
  toRef,
  watch,
} from 'vue';
import {
  boolean as BooleanColFilter,
  date as DateColFilter,
  input as InputColFilter,
} from './col-filter';
import CmdColumn from './column/CmdColumn';
import EnumColumn from './column/EnumColumn';
import LinkColumn from './column/LinkColumn';
import HintCol from './hintCol';
import styles from './index.module.scss';
import './index.scss';
import useDataGrid, {
  useDataGridOpts,
  useDataGridOptsProps,
  useDataGridProps,
  useOpts,
  zipObject,
} from './use-data-grid';

import _, { forIn, orderBy } from 'lodash';

import {
  filterRowWithDate,
  useOperationProps,
} from './col-filter/use-col-filter';

export * from 't/basic/table/Component';
import ColumnSetting from './components/ColumnSetting';
import { useI18n } from 'vue-i18n';
import { mergeFilters, mergeFiltersBase } from 't/common/utils';

import {
  date,
  debounce,
  dom,
  setCssVar,
  useQuasar,
  scroll,
} from '@teld/q-components';

import {
  useTableFilter,
  useTablePaginationState,
} from '@teld/q-components/Table';

import Sortable from './lib/sortable.esm';
import { isDef } from '@vueuse/core';

import * as echarts from 'echarts';

import TQuickFilter from 't/bussiness/quick-filter';
import {
  propsSuffix,
  pickProps,
  mappingEvent,
} from 't/bussiness/mixed-view/utils';
import label from 't/basic/label';

const C = {
  dynamicMinHeight: 350,
  UNSET: 'unset',
};

export default defineComponent({
  name: 'TDataGrid',
  props: {
    mockData: {
      type: [Object, String],
      default() {
        return {
          columns: [],
          rows: [],
        };
      },
    },
    ...commonProps,
    ...TTable.props,
    ...useDataGridProps,
    ...useDataGridOptsProps,

    showPopupColumnsSetting: {
      type: Boolean,
      default() {
        return false;
      },
    },
    disableFixedColumn: {
      type: Boolean,
      default() {
        return false;
      },
    },
    menuModel: {
      type: Boolean,
      default() {
        return false;
      },
    },
    menuDataSource: {
      type: Array,
      default() {
        return [];
      },
    },
    enableGrouping: {
      type: Boolean,
      default() {
        return false;
      },
    },
    isGrouping: {
      type: Boolean,
      default() {
        return false;
      },
    },
    enableGroupingAllItem: {
      type: Boolean,
      default() {
        return true;
      },
    },
    showGroupingTotalCount: {
      type: Boolean,
      default() {
        return true;
      },
    },
    dynamicMinHeight: {
      type: Number,
      default() {
        return C.dynamicMinHeight;
      },
    },
    dynamicFullLoading: {
      type: Boolean,
      default() {
        return false;
      },
    },
    fixedHeader: {
      type: Boolean,
      default() {
        return false;
      },
    },
    fixedHeaderOffsetTop: {
      type: Number,
      default() {
        return 0;
      },
    },
    fixedHeaderPadding: {
      type: String,
      default() {
        return 'unset';
      },
    },
    fixedHeaderPaddingTop: {
      type: Number,
      default() {
        return 0;
      },
    },
    fixedHeaderBackgroundColor: {
      type: String,
      default() {
        return '#FFF';
      },
    },
    fixedHeaderZindex: {
      type: Number,
      default() {
        return 190;
      },
    },
    groupItemSummary: TQuickFilter.props.quickItemSummary,
    simplePaging: {
      type: Boolean,
      default() {
        return false;
      },
    },
    paginationStyle: {
      type: String,
      default() {
        return C.UNSET;
      },
    },
    paddingLeft: {
      type: Number,
      default() {
        return 0;
      },
    },
    headers: {
      type: Array,
      default() {
        return [];
        /*
        return [
          {
            label: '用户信息',
            children: [
              {
                label: '基本信息',
                children: [{ dataField: 'name' }, { dataField: 'age' }],
              },
              {
                label: '联系方式',
                children: [{ dataField: 'phone' }],
              },
            ],
          },
        ];
        */
      },
    },
    // ...propsSuffix(TQuickFilter.props, '_QuickGroupFilter'),
  },
  emits: [
    // 'update:showAutoFilterRow',
    'update:pagination',
    'request',
    'columnChanged',
    'cmdColClick',
    'selectionChanged',
    'row_click',
    'pageChange',
    'pageSizeChange',
    'dataSourceLoaded',
    'UpdateAdvQuery',
    'UpdateAdvQueryWithUserProfile',
    'UpdateAdvQueryWithResetSort',
    'UpdateAdvQueryWithPageSizeChange',
    'beforeContextMenuShow',
    'contextMenuClick',
    'groupChanged',
    'groupSummary',
    'groupFieldChange',
  ],

  setup(props, { attrs, emit, expose, slots }) {
    const vm = getCurrentInstance();
    const $q = useQuasar();
    const { t } = useI18n({ useScope: 'global' });

    const refComponent = ref();
    const refRoot = ref();
    const selected = toRef(props.selected);
    const showAutoFilterRow = toRef(props.showAutoFilterRow);
    const menuDataSource = toRef(props.menuDataSource);

    const EnableMask = ref(false);

    const pagination = computed({
      get() {
        return props.pagination;
      },
      set(val) {
        update('pagination', val);
      },
    });

    // const reactiveSortBy = reactive({ sortBy: '', descending: '' });
    const filteredSortedRows = computed(() => {
      let rows = props.rows;
      rows = _.orderBy(
        rows,
        columnSortBy.map(item => item.field),
        columnSortBy.map(item => item.sort),
      );

      if (props.filter) {
        rows = computedFilterMethod.value(
          rows,
          props.filter,
          computedCols.value,
          getCellValue,
        );
      }

      return rows;
    });

    const filteredSortedRowsNumber = computed(
      () => filteredSortedRows.value.length,
    );

    const rowsFilter = ref({});

    const filterRowWithBoolean = (value, filter) => {
      // 兼容 "0" 和 "1" 为 true/false 及 显示映射
      let boolValue = value == 'false' ? false : value == 'true' ? true : value;
      return !!+boolValue == filter.filterValue;
      /*
      return filterRowDefault(value, {
        // col: filter.col,
        // filterValue: filter.filterValue,
        ...filter,
        name: '=',
      });
      */
    };
    const filterRowValueMapping = (value, filter) => {
      let { valMapping, enumRanges } = filter?.col?.optCol?.enumDisp || {};
      if (valMapping && enumRanges && enumRanges.length > 0) {
        let mappingValue = enumRanges.find(item => item.val == value);
        if (mappingValue) {
          value = mappingValue.text;
        }
      }
      return value;
    };
    const filterRowWithInput = (value, filter) => {
      value = filterRowValueMapping(value, filter);
      let lowerCaseValue = value?.toLowerCase();
      let lowerCaseFilterValue = filter.filterValue?.toLowerCase()?.trim();
      let lowerCaseTrimFilterValue = lowerCaseFilterValue?.trim();
      switch (filter.name) {
        default:
        case 'contains':
          return `${lowerCaseValue}`.includes(lowerCaseTrimFilterValue);
          break;
        case '=':
          return lowerCaseValue == lowerCaseTrimFilterValue;
          break;
        case '>':
          return lowerCaseValue > lowerCaseTrimFilterValue;
          break;
        case 'notcontains':
          return (
            false === `${lowerCaseValue}`.includes(lowerCaseTrimFilterValue)
          );
          break;
        case 'startswith':
          return `${lowerCaseValue}`.startsWith(lowerCaseTrimFilterValue);
          break;
        case 'endswith':
          return `${lowerCaseValue}`.endsWith(lowerCaseTrimFilterValue);
          break;
      }
    };
    const filterRowDefault = (value, filter) => {
      value = filterRowValueMapping(value, filter);
      let filterValue = filter.filterValue?.trim();

      switch (filter.name) {
        default:
        case 'contains':
          return `${value}`.includes(filterValue);
          break;
        case 'notcontains':
          return false === `${value}`.includes(filterValue);
          break;
        case 'startswith':
          return `${value}`.startsWith(filterValue);
          break;
        case 'endswith':
          return `${value}`.endsWith(filterValue);
          break;
        case '=':
          return value == filterValue;
          break;
        case '>':
          return value > filter.filterValue;
          break;
        case '<>':
          return value != filterValue;
          break;
        case '<':
          return value < filter.filterValue;
          break;
        case '<=':
          return value <= filter.filterValue;
          break;
        case '>':
          return value > filter.filterValue;
          break;
        case '>=':
          return value >= filter.filterValue;
          break;
      }
    };

    const filterRow = rows => {
      let filterConf = rowsFilter.value;
      Object.keys(filterConf).forEach(field => {
        let filter = filterConf[field];
        filter.col = filterByColumn[field].col;
        if (
          filter.filterValue ||
          true === filter.filterValue ||
          false === filter.filterValue
        ) {
          rows = rows.filter(item => {
            let value = item[field];
            switch (filter.dataType?.toLowerCase()) {
              case 'date':
              case 'datetime':
              case 'timestamp':
                return filterRowWithDate(value, filter);
                break;
              case 'boolean':
                return filterRowWithBoolean(value, filter);
                break;
              case 'string':
                return filterRowWithInput(value, filter);
                break;
              default:
                return filterRowDefault(value, filter);
                break;
            }
          });
        }
      });
      return rows;
    };

    let columnSortBy = reactive([]);
    const columnKeys = computed(() =>
      _.transform(
        columnSortBy,
        (r, v, index) => {
          r[v.field] = { sort: v.sort, index: index };
        },
        {},
      ),
    );

    let columnSortByWithQueryPlan = ref([]);

    const computedRows = computed(() => {
      let rows = filteredSortedRows.value;

      rows = filterRow(rows);

      if (isServerSide.value === true) {
        return rows;
      }

      const { rowsPerPage } = computedPagination.value;

      if (rowsPerPage !== 0) {
        if (firstRowIndex.value === 0 && props.rows !== rows) {
          if (rows.length > lastRowIndex.value) {
            rows = rows.slice(0, lastRowIndex.value);
          }
        } else {
          rows = rows.slice(firstRowIndex.value, lastRowIndex.value);
        }
      }
      return rows;
    });

    const {
      // innerPagination,
      // computedPagination,
      // isServerSide,

      // requestServerInteraction,
      setPagination,
    } = useTablePaginationState(vm, getCellValue);

    const isServerSide = ref(true);

    const { computedFilterMethod } = useTableFilter(props, setPagination);

    const { hasHeaderSlot } = useDataGrid(props, slots);

    const setFixedColumnShadow = root => {
      root.querySelectorAll('.q-table tr').forEach(tr => {
        let fixedLeft = tr.querySelectorAll('.fixed-column-left');
        fixedLeft &&
          fixedLeft.length > 0 &&
          fixedLeft[fixedLeft.length - 1].classList.add(
            'fixed-column-left-shadow',
          );

        let fixedRight = tr.querySelectorAll('.sticky.right');
        fixedRight &&
          fixedRight.length > 0 &&
          fixedRight[0].classList.add('fixed-column-right-shadow');
      });
    };

    function setFixedHeaderFixedColumn(root) {
      let s_fixed = [];
      root = root || refRoot.value;

      let selectColumn = root.querySelectorAll(
        '.t-fixed-header th.q-table--col-auto-width:first-Child:not(.fixed-column-left)',
      );

      let fixedColumn = root.querySelectorAll(
        '.t-fixed-header th.fixed-column-left',
      );

      if (fixedColumn.length > 0) {
        fixedColumn = [...selectColumn, ...fixedColumn];
      }
      fixedColumn.forEach(col => {
        let colLeft = 0;
        let colMinWidth = col.getBoundingClientRect().width;
        if (colMinWidth == 0) {
          return;
        }
        if (s_fixed.length > 0) {
          colLeft =
            s_fixed[s_fixed.length - 1].left +
            s_fixed[s_fixed.length - 1].minWidth;
        }
        s_fixed.push({ left: colLeft, minWidth: colMinWidth });
        if (!col.style.left) {
          col.style.left = colLeft + 'px';
          col.style.maxWidth = col.style.minWidth = colMinWidth + 'px';
        }
      });
    }

    const setFixedColumn = (opts = { forceLeft: false }) => {
      if (props.disableFixedColumn) {
        return;
      }

      let root = refRoot.value;
      if (root) {

        const isSelection = 'none' !== mappingProps.selection;
        root.querySelectorAll('div.selectionBox').forEach(selBox => {
          const p = selBox.closest('th') || selBox.closest('td');
          if (p) {
            if (isSelection) {
              p.classList.add('fixed-column-left');
              p.classList.add('selectionCol');
            } else {
              p.classList.remove('fixed-column-left');
            }
          }
        });
        if ('single' == mappingProps.selection) {
          const a = root.querySelector("thead tr th:first-child.q-table--col-auto-width")
          if(a){
            a.classList.add('fixed-column-left');
            a.classList.add('selectionCol');
          }
        }


        let { left, right } = root.getBoundingClientRect();
        let scrollLeft =
          root.querySelectorAll('.q-virtual-scroll')[0].scrollLeft;
        let scrollRight =
          root.querySelectorAll('.q-virtual-scroll')[0].scrollLeft;
        let s = [];
        root
          .querySelectorAll('.t-data-grid--main th.fixed-column-left')
          .forEach((col, cIndex) => {
            const clientRect = col.getBoundingClientRect();
            if (0 === clientRect.width) {
              return;
            }

            let clientRectLeft = clientRect.left;
            if (0 === cIndex) {
              clientRectLeft = left;
            }

            let colLeft = clientRectLeft - left;
            if ($q?.platform?.is?.mobile) {
              colLeft -= mappingProps.paddingLeft * 2;
            }
            let colMinWidth = col.getBoundingClientRect().width;
            if (colMinWidth == 0) {
              return;
            }
            if (s.length > 0) {
              colLeft = s[s.length - 1].left + s[s.length - 1].minWidth;
            }
            s.push({ left: colLeft, minWidth: colMinWidth });
            if (!col.style.left) {
              col.style.left = colLeft + 'px';
              col.style.maxWidth = col.style.minWidth = colMinWidth + 'px';
            }
            if (opts.forceLeft) {
              col.style.left = colLeft + 'px';
            }
            // col.style.left = colLeft + "px";
            // col.style.maxWidth = col.style.minWidth = colMinWidth + "px";
          });

        setFixedHeaderFixedColumn(root);

        let sCount = s.length;
        let sIndex = 0;

        root.querySelectorAll('tbody tr').forEach(tr => {
          tr.querySelectorAll('td.fixed-column-left').forEach(
            (col, colIndex) => {
              if (!col.style.left) {
                col.style.left = s[colIndex]?.left + 'px';
              }
              if (opts.forceLeft) {
                col.style.left = s[colIndex]?.left + 'px';
              }
              // col.style.maxWidth = col.style.minWidth = s[colIndex].minWidth + "px";
            },
          );
        });

        let rightCols = root.querySelectorAll('.fixed-column-right');
        for (let index = rightCols.length - 1; index >= 0; index--) {
          // const element = array[index];
          let col = rightCols[index];
          col.style.right =
            right + scrollLeft - col.getBoundingClientRect().right + 'px';
        }
        setFixedColumnShadow(root);
        scrollHover();
      }
    };

    const setFixedColumnByMousemove = () => {
      if (props.disableFixedColumn) {
        return;
      }

      let root = refRoot.value;
      if (root) {
        let s = [];
        root.querySelectorAll('th.fixed-column-left').forEach(col => {
          s.push({ left: col.style.left, minWidth: col.style.minWidth });
        });
        let sCount = s.length;
        let sIndex = 0;

        root.querySelectorAll('tbody tr').forEach(tr => {
          tr.querySelectorAll('td.fixed-column-left').forEach(
            (col, colIndex) => {
              if (s[colIndex]) col.style.left = s[colIndex].left;
            },
          );
        });
        setFixedColumnShadow(root);
      }
    };

    function hasScrollbar(element) {
      const style = window.getComputedStyle(element);
      const overflowY = style.overflowY;
      const clientHeight = element.clientHeight;
      const scrollHeight = element.scrollHeight;
      const clientWidth = element.clientWidth;
      const scrollWidth = element.scrollWidth;

      const hasScrollY =
        (overflowY === 'scroll' || overflowY === 'auto') &&
        scrollHeight > clientHeight;

      const hasScrollX = scrollWidth > clientWidth;
      return { hasScrollY, hasScrollX };
    }

    function scrollHover() {
      if (refRoot.value && refRoot.value.querySelector) {
        let elScroll = refRoot.value.querySelector(
          '.scrollbar-hover-visible .q-virtual-scroll',
        );
        setTimeout(() => {
          const { hasScrollY, hasScrollX } = hasScrollbar(elScroll);
          if (hasScrollY) {
            elScroll.classList.add('has-scrollbar');
            refHeader.value?.classList.add('has-scrollbar');
          } else {
            elScroll.classList.remove('has-scrollbar');
            refHeader.value?.classList.remove('has-scrollbar');
          }
          if (hasScrollX) {
            elScroll.classList.add('has-x-scrollbar');
            refHeader.value?.classList.add('has-x-scrollbar');

            elScroll.classList.remove('no-x-scrollbar');
            refHeader.value?.classList.remove('no-x-scrollbar');
          } else {
            elScroll.classList.remove('has-x-scrollbar');
            refHeader.value?.classList.remove('has-x-scrollbar');

            elScroll.classList.add('no-x-scrollbar');
            refHeader.value?.classList.add('no-x-scrollbar');
          }
        }, 300);
      }
    }

    const scrollDeadZoneRightMode = ref(true);
    function scrollDeadZoneRight(event) {
      console.groupCollapsed('scrollDeadZoneRight');
      console.log(event);
      const deadZoneRight = 8;
      const currentTarget = event.currentTarget; // 当前滚动位置

      const scrollLeft = currentTarget.scrollLeft; // 当前滚动位置
      const scrollWidth = currentTarget.scrollWidth; // 内容总宽度
      const clientWidth = currentTarget.clientWidth; // 可视区域宽度

      if (scrollDeadZoneRightMode.value === false) {
        console.log('直接改');
        if (scrollLeft + clientWidth > scrollWidth - deadZoneRight) {
          currentTarget.scrollLeft = scrollWidth - clientWidth - deadZoneRight; // 固定在死区边界
        }
      } else {
        console.log('requestAnimationFrame');
        if (!ticking) {
          window.requestAnimationFrame(() => {
            // doSomething(lastKnownScrollPosition);
            const scrollLeft = currentTarget.scrollLeft; // 当前滚动位置
            const scrollWidth = currentTarget.scrollWidth; // 内容总宽度
            const clientWidth = currentTarget.clientWidth; // 可视区域宽度

            if (scrollLeft + clientWidth > scrollWidth - deadZoneRight) {
              currentTarget.scrollLeft =
                scrollWidth - clientWidth - deadZoneRight; // 固定在死区边界
            }

            ticking = false;
          });

          ticking = true;
        }
      }
      console.groupEnd();
    }

    let ticking = false;

    function setupScrollHover() {
      if (refRoot.value && refRoot.value.querySelector) {
        let elScroll = refRoot.value.querySelector(
          '.scrollbar-hover-visible .q-virtual-scroll',
        );

        elScroll.addEventListener('mouseover', scrollHover);
        elScroll.addEventListener('scroll', onScrollHandler);
        // elScroll.addEventListener('scroll', scrollDeadZoneRight);
      }
    }

    let resizeObserver = null;
    onMounted(() => {
      if (false && props.allowColumnMoving) {
        sortableColumns();
      }
      setupScrollHover();

      resizeObserver = new ResizeObserver(entries => {
        for (let entry of entries) {
          const { height: pHeight } =
            refQuickGroupDiv.value.getBoundingClientRect();
          const { height: qHeight } =
            refQuickFilter.value.$el.getBoundingClientRect();
          isOverflow.value = qHeight > pHeight;
          console.log(
            `pHeight${pHeight}px，qHeight：${qHeight}px`,
            isOverflow.value,
          );
          // isOverflowFlag.value = isOverflow.value;
          setFixedColumn();

          // 在这里可以执行更多操作，例如更新状态或调用函数
        }
      });
    });
    onUnmounted(() => {
      // 组件卸载时，停止监听
      if (resizeObserver) {
        resizeObserver.disconnect();
      }

      if (refRoot.value && refRoot.value.querySelector) {
        let elScroll = refRoot.value.querySelector(
          '.scrollbar-hover-visible .q-virtual-scroll',
        );
        elScroll.removeEventListener('mouseover', scrollHover);
        elScroll.removeEventListener('scroll', onScrollHandler);
        // elScroll.removeEventListener('scroll', scrollDeadZoneRight);
      }
    });

    const f = (vCols, new_index, old_index) => {
      const skip = ['stickyCmdColumn', 'rowNumberColumn'];
      console.group('FFFF');
      console.log('FFFF', vCols.join(','));
      console.log('FFFF', vCols[new_index], vCols[old_index]);
      let newVal = vCols[new_index];
      let oldVal = vCols[old_index];
      vCols[new_index] = oldVal;
      vCols[old_index] = newVal;
      console.log('FFFF', vCols[new_index], vCols[old_index]);
      console.log('FFFF', vCols.join(','));
      vCols = _.filter(vCols, col => false === skip.includes(col));
      console.log('FFFF', vCols.join(','));
      console.groupEnd();
      return vCols;
    };
    const sortableColumns = () => {
      let dom = refComponent.value.$el;
      const domColumns = dom.querySelector('table thead tr:nth-of-type(1)');
      if (!domColumns) {
        return;
      }
      const sortableColumns = Sortable.create(domColumns, {
        filter: '.ignore-elements',
        // preventOnFilter: true,
        // disabled: !draggable_columns,
        onEnd(event) {
          debugger;

          let old_index = event.oldIndex,
            new_index = event.newIndex;
          // if (self.selection) {
          //   old_index = old_index - 1;
          //   new_index = new_index - 1;
          // }

          // old_index = old_index - 1;
          // new_index = new_index - 1;

          const skip = ['stickyCmdColumn', 'rowNumberColumn'];
          let vCols = _.map(mOpts.value.visibleColumns, col => col);
          let vCols1 = _.map(mOpts.value.visibleColumns, col => col);
          let vCols2 = _.map(mOpts.value.visibleColumns, col => col);
          // let vCols = _.filter(mOpts.value.visibleColumns, col => false === skip.includes(col))

          // f(vCols, new_index, old_index)
          // f(vCols1, new_index - 1, old_index - 1)
          // f(vCols2, new_index - 2, old_index - 2)

          // vCols = _.filter(vCols, col => false === skip.includes(col))

          setTimeout(() => {
            updateVisibleColumns(f(vCols2, new_index - 2, old_index - 2));
          }, 100);
          // updateVisibleColumns(vCols);
          // updateVisibleColumns(['UserName', 'Alias', 'Account'])
          // if (event.newIndex != 0) {
          // let old_index, new_index;
          // if (self.selection) {
          //   old_index = event.oldIndex - 1;
          //   new_index = event.newIndex - 1;
          // } else {
          //   old_index = event.oldIndex;
          //   new_index = event.newIndex;
          // }
          // let visibleColumns = bind.computedVisibleColumns.value;
          // let oldField = visibleColumns[old_index];
          // let newField = visibleColumns[new_index];
          // old_index = columns.value.findIndex(col => col.field == oldField);
          // new_index = columns.value.findIndex(col => col.field == newField);
          // let tmp = columns.value[old_index];
          // columns.value[old_index] = columns.value[new_index];
          // columns.value[new_index] = tmp;
          // emit('columnChanged', {
          //   dragged_column: columns.value[old_index],
          //   old_index: old_index,
          //   new_index: new_index,
          // });
        },
        onMove: function (/**Event*/ evt, /**Event*/ originalEvent) {
          if (evt.related.className.includes('ignore-elements')) {
            return false;
          }
        },
      });
    };

    function onClickHandler(params) {}

    const columnsFilterColRender = (props, col) => {
      return <div>{col.name}</div>;
    };

    // const showAutoFilterRow = computed(() => props.showAutoFilterRow);

    function getCellValue(col, row) {
      const val =
        typeof col.field === 'function' ? col.field(row) : row[col.field];
      return col.format !== void 0 ? col.format(val, row) : val;
    }

    const colFilterChanged = debounce(function () {
      rowsFilter.value = { ...reactiveFilter };
    }, 200);

    const getColFilter = (col, slotProps) => {
      if (!col.field) {
        return;
      }

      const dataType = col.optCol.dataType?.toLowerCase();
      switch (dataType) {
        case 'date':
        case 'datetime':
          return (
            <DateColFilter
              props={slotProps}
              onChange={colFilterChanged}
              dataType={dataType}
              v-model:operation={reactiveFilter[col.field]}
            />
          );
          break;
        case 'timestamp':
          return (
            <DateColFilter
              props={slotProps}
              onChange={colFilterChanged}
              dataType='datetime'
              v-model:operation={reactiveFilter[col.field]}
            />
          );
          break;
        case 'boolean':
          return (
            <BooleanColFilter
              props={slotProps}
              onChange={colFilterChanged}
              dataType={dataType}
              v-model:operation={reactiveFilter[col.field]}
            ></BooleanColFilter>
          );
        default:
          return (
            <>
              {/* [{JSON.stringify(reactiveFilter[col.field])}] */}
              <InputColFilter
                props={slotProps}
                onChange={colFilterChanged}
                dataType={dataType}
                v-model:operation={reactiveFilter[col.field]}
              />
            </>
          );
          break;
      }
    };

    const clearFilter = () => {
      Object.keys(reactiveFilter).forEach(key => {
        delete reactiveFilter[key].filterValue;
      });
      colFilterChanged();
    };

    watch(
      () => showAutoFilterRow.value,
      val => {
        if (false === val) {
          clearFilter();
        } else {
          if (refRoot.value) {
            setTimeout(() => {
              setFixedColumnShadow(refRoot.value);
            }, 100);
          }
        }
      },
    );

    const slotTopRow = slotProps => {
      return (
        showAutoFilterRow.value &&
        true != mappingProps.hideHeader && (
          <tr
            style={{
              '--t-columnsFilter-top': isMultiMeader.value
                ? `${computedHeaders.value.maxDepth * 48}px`
                : '48px',
            }}
            class={[styles.columnsFilter, 'columnsFilter']}
          >
            {props.selection != 'none' && (
              <td
                style='z-index:111;border-bottom-width: 1px; background-color: #fff;min-width: 52px;'
                class={[!props.disableFixedColumn && 'checkbox-filter']}
              ></td>
            )}
            {/* {mappingProps.showRowNumber && <td></td>} */}
            {slotProps.cols.map(col => (
              <td
                style='z-index:110;padding-left: 0px; padding-right:0px; border-bottom-width: 1px; background-color: #fff;'
                class={[
                  col.classes,
                  !props.disableFixedColumn &&
                    col.name == 'rowNumberColumn' &&
                    'fixed-column-left',
                  col.name == 'stickyCmdColumn' && 'sticky right',
                ]}
              >
                {getColFilter(col, slotProps)}
              </td>
            ))}
          </tr>
        )
      );
    };

    const cellLinkHref = props => {
      cellClickInfo = {
        data: props.row,
      };
      new Function(props.col.optCol.linkFormat)();
    };

    const cellSlotLink = cellParam => {
      return (
        <div>
          {props.menuModel ? contextMenuList(cellParam) : null}
          <LinkColumn
            cellParam={cellParam}
            record={cellParam.row}
            column={cellParam.col.optCol}
            rowIndex={cellParam.rowIndex}
            onColumnLinkFormat={() => {
              if (props.columnLinkFormat) {
                mappingExpose.cellClickInfo = {
                  data: cellParam.row,
                };
                props.columnLinkFormat(cellParam.col.field);
              }
            }}
          />
        </div>
      );
    };

    const cellSlotEnum = cellParam => {
      return (
        <>
          <div>
            {props.menuModel ? contextMenuList(cellParam) : null}
            <EnumColumn
              cellParam={cellParam}
              record={cellParam.row}
              column={cellParam.col.optCol}
              rowIndex={cellParam.rowIndex}
              isDev={props.isDev}
              onColumnLinkFormat={() => {
                let linkFormat = cellParam.col?.optCol?.linkFormat;
                if (props.columnLinkFormat && linkFormat) {
                  mappingExpose.cellClickInfo = {
                    data: cellParam.row,
                  };
                  props.columnLinkFormat(cellParam.col.field);
                }
              }}
            />
          </div>
        </>
      );
    };

    const setColCmdInfo = (cmd, data) => {
      mappingExpose.colCmdInfo = {
        command: cmd,
        data: data,
      };
    };

    const cellSlotCmd = cellParam => {
      return (
        <CmdColumn
          record={cellParam.row}
          cmdColConfig={cellParam.col.cmdColConfig}
          rowIndex={cellParam.rowIndex}
          colCommandVisible={(cmd, data) => {
            if (props.colCommandVisible && cmd.exprVisible) {
              setColCmdInfo(cmd, cellParam.row);
              return props.colCommandVisible(cmd);
            } else {
              return true;
            }
          }}
          onCmdColClick={cmd => {
            if (props.cmdColClick && cmd.clientScript) {
              setColCmdInfo(cmd, cellParam.row);
              props.cmdColClick(cmd);
            }
          }}
        />
      );
    };

    const bodyCellBoolean = cellParam => {
      return (
        <TTd props={cellParam} onClick={e => e.stopPropagation()}>
          {props.menuModel ? contextMenuList(cellParam) : null}
          <TCheckbox
            tabindex='-1'
            style='pointer-events: none;'
            v-model={cellParam.value}
          />
        </TTd>
      );
    };

    const dateFormat = {
      date: 'YYYY/MM/DD',
      datetime: 'YYYY/MM/DD HH:mm:ss',
      time: 'HH:mm:ss',
    };
    const dateFormatFunc = {
      date: 'DateToString',
      datetime: 'DateTimeToString',
      timestamp: 'DateTimeToString',
      time: 'DateTimeToTime',
    };
    const bodyCellDate = cellParam => {
      let funcFormatDate;
      let dataTypeLowerCase = cellParam?.col?.optCol?.dataType?.toLowerCase();
      if (Funcs && false === props.isDev) {
        funcFormatDate =
          Funcs[dateFormatFunc[dataTypeLowerCase]] || Funcs.DateTimeToString;
      }
      let format = dateFormat[dataTypeLowerCase] || 'YYYY/MM/DD HH:mm:ss';
      return (
        <TTd props={cellParam}>
          {funcFormatDate
            ? cellParam.value
              ? funcFormatDate(cellParam.value)
              : ''
            : date.formatDate(cellParam.value, format)}
          {props.menuModel ? contextMenuList(cellParam) : null}
        </TTd>
      );
    };

    const bodyCellCustomContent = rowData => {
      let expression = rowData?.col?.optCol?.customCellContent;
      let fixWidth = rowData?.col?.optCol?.width;
      if (fixWidth && false == isNaN(+fixWidth)) {
        fixWidth = fixWidth + 'px';
      }
      if (expression) {
        if (typeof expression == 'string') {
          try {
            const expressionFunc = new Function('rowData', expression);
            const jsxResult = expressionFunc(rowData);
            // console.log(jsxResult);
            return (
              <TTd props={rowData}>
                <div v-html={jsxResult} onClick={() => {
                  let linkFormat = rowData.col?.optCol?.linkFormat;
                  if (props.columnLinkFormat && linkFormat) {
                    mappingExpose.cellClickInfo = {
                      data: rowData.row,
                    };
                    props.columnLinkFormat(rowData.col.field);
                  }
                }}></div>
                {props.menuModel ? contextMenuList(rowData) : null}
              </TTd>
            );
          } catch (error) {
            console.error(error);
            return <TTd props={rowData}>{rowData.value}</TTd>;
          }
        }
        if (typeof expression == 'object') {
          let bg = expression?.background ? expression.background : [];
          let font = expression?.font ? expression.font : [];
          let wrap = expression?.wrap ? expression.wrap : [];
          return (
            <TTd
              props={rowData}
              style={{
                ...bg,
              }}
            >
              <div
                style={{
                  ...font,
                  ...wrap,
                  'width': fixWidth ? fixWidth : 'auto',
                  'min-width': fixWidth ? fixWidth : 'auto',
                  'max-width': fixWidth ? fixWidth : 'auto',
                }}
              >
                {typeof rowData.value === 'boolean'
                  ? rowData.value.toString()
                  : rowData.value}
              </div>
              {props.menuModel ? contextMenuList(rowData) : null}
            </TTd>
          );
        }
      }
    };
    const bodyCellCharts = rowData => {
      nextTick(() => {
        setTimeout(() => {
          let chartDom = document.getElementById(
            'chart_' + rowData.col.field + '_' + rowData.rowIndex,
          );
          let myChart = echarts.init(chartDom);
          let option = null;
          let field = rowData.col.optCol?.chartOptions?.yAxisData;
          let fieldData = field ? rowData.row[field] : null;
          if (typeof fieldData == 'string') {
            let array = fieldData.split(',');
            fieldData = array.map(item => {
              return parseFloat(item);
            });
          }
          if (typeof fieldData == 'number') {
            fieldData = [fieldData];
          }
          if (
            !fieldData ||
            !Array.isArray(fieldData) ||
            fieldData.length == 0
          ) {
            return;
          }
          if (
            rowData.col.optCol?.chartOptions.type == 'line' ||
            rowData.col.optCol?.chartOptions.type == 'bar'
          ) {
            option = {
              grid: {
                top: 5,
                left: 0,
                bottom: 5,
                right: 0,
              },
              xAxis: {
                type: 'category',
                // data: rowData.col.optCol?.chartOptions.xAxisData,
                show: false,
              },
              yAxis: {
                type: 'value',
                show: false,
              },
              series:
                rowData.col.optCol?.chartOptions.type == 'line'
                  ? [
                      {
                        data: fieldData,
                        type: 'line',
                        smooth: true,
                        showSymbol: false,
                      },
                    ]
                  : [
                      {
                        data: fieldData,
                        type: 'bar',
                      },
                    ],
            };
            if (rowData.col.optCol?.chartOptions.color) {
              option.color = [rowData.col.optCol?.chartOptions.color];
            }
          }
          if (rowData.col.optCol?.chartOptions.type == 'pie') {
            option = {
              tooltip: {
                trigger: 'item',
                show: false,
              },
              legend: {
                top: '5%',
                left: 'center',
                show: false,
              },
              series: [
                {
                  type: 'pie',
                  radius: ['40%', '70%'],
                  center: ['30%', '50%'],
                  label: {
                    show: false,
                    position: 'center',
                    formatter: '{d}%',
                  },
                  emphasis: {
                    label: {
                      show: rowData.col.optCol?.chartOptions.showValue,
                    },
                    scale: false,
                  },
                  labelLine: {
                    show: false,
                  },
                  data: fieldData,
                },
              ],
            };
          }
          option && myChart.setOption(option);
          // if (rowData.col.optCol?.chartOptions.expression) {
          //   let ex = new Function(rowData.col.optCol.chartOptions.expression);
          //   myChart.on('click', function (params) {
          //     try {
          //       ex();
          //     } catch (error) {
          //       console.error(error);
          //     }
          //   });
          // }
        }, 10);
      });

      return (
        <TTd props={rowData}>
          <div
            id={'chart_' + rowData.col.field + '_' + rowData.rowIndex}
            style={{
              height: '100%',
              width: rowData.col.optCol?.chartOptions.width
                ? rowData.col.optCol?.chartOptions.width + 'px'
                : '100%',
            }}
          >
            {rowData.value}
          </div>
          {props.menuModel ? contextMenuList(rowData) : null}
        </TTd>
      );
    };

    const contextMenuList = rowData => {
      return (
        <TMenu
          touch-position
          context-menu
          class={[styles.contextMenu]}
          onBeforeShow={evt => beforeContextmenu(rowData)}
        >
          <TList>
            {Array.isArray(props.menuDataSource)
              ? props.menuDataSource.map(item => {
                  return (
                    <TItem
                      class={[styles.contextMenuItem]}
                      clickable
                      v-close-popup
                      onClick={e => contextMenuClick(e, rowData, item)}
                      disable={item.disabled}
                    >
                      <TItemSection class='q-pr-none'>
                        <div class={[styles.contextMenuItemSection]}>
                          <div class={[styles.icon]} v-show={item.Icon}>
                            <TIcon name={item.Icon} />
                          </div>
                          <div>{item.Name}</div>
                        </div>
                      </TItemSection>
                    </TItem>
                  );
                })
              : ''}
          </TList>
        </TMenu>
      );
    };
    const contextMenuClick = (e, rowData, item) => {
      emit('contextMenuClick', { row: rowData, item:item });
    };
    const bodyCellCmd = cellParam => {
      return (
        <TTd
          onClick={e => {
            e.stopPropagation();
          }}
          class='td-cmdColumn'
          style='text-overflow: unset; text-align: left; padding-left: 0;padding-right: 0;' /** yifei：给出方案，处理按钮组宽度问题 */
          props={cellParam}
          onMousemove={e => {
            if (e.currentTarget && e.currentTarget.title) {
              e.currentTarget.title = '';
            }
          }}
        >
          <div style='width:24px; display: inline-block;'></div>
          {cellSlotCmd(cellParam)}
        </TTd>
      );
    };

    const bodyCellRowNumber = cellParam => {
      const rowIndex = props.isDev
        ? cellParam.rowIndex
        : cellParam.row._rowNumber;
      return (
        <TTd
          class={['row-number', 'none' != mappingProps.selection && 'left50px']}
          props={cellParam}
        >
          {rowIndex + 1}
        </TTd>
      );
    };

    const bodySelection = scope => {
      return (
        <div class='selectionBox'>
          {'single' === mappingProps.selection ? (
            <TRadio
              size='xs'
              keep-color
              color="primary"
              tabindex='1'
              onClick={() => {
                scope.selected = !scope.selected;
              }}
              model-value={scope.selected}
              val={true}
            />
          ) : (
            <TCheckbox tabindex='1' v-model={scope.selected} />
          )}
        </div>
      );
    };

    const headerCellRowNumber = (
      cellParam,
      extProps = {
        class: [
          'header-row-number',
          'none' != mappingProps.selection && 'left50px',
        ],
      },
    ) => {
      return (
        <TTh {...extProps} props={cellParam}>
          {$q.lang.dataGrid?.rowNumber}
        </TTh>
      );
    };

    const bodyCellLink = cellParam => {
      return <TTd props={cellParam}>{cellSlotLink(cellParam)}</TTd>;
    };
    const bodyCellEnum = cellParam => {
      return <TTd props={cellParam}>{cellSlotEnum(cellParam)}</TTd>;
    };

    const headerCellHint = cellParam => {
      const cellInfo = { column: cellParam.col.optCol };
      return <HintCol column={cellParam.col.optCol} isDevEnv={props.isDev} />;
    };

    const update = (prop, propValue) => {
      emit(`update:${prop}`, propValue);
    };

    const btnClick = () => {
      // emit('update:showAutoFilterRow', !props.showAutoFilterRow);
      emit('aaa', { a: 1 });
      setCssVar('primary', '#33F');
      console.log($q.screen.height);
    };

    const twoWayProps = usePropsTwoWayValues(['showPopupColumnsSetting']);

    const execQuery = () => {
      mappingExpose.pageIndex.value = 1;
      if (computedPagination.value?.rowsPerPage) {
        mappingExpose.pageSize.value = computedPagination.value.rowsPerPage;
      }

      emit('request', {
        // pagination: {
        //   page: 1,
        //   rowsPerPage: 1,
        // },
        pagination: { ...computedPagination.value, page: 1 },
        filter: '',
        getCellValue,
      });
    };

    const query = () => {
      // refComponent.value.requestServerInteraction({
      //   pagination: computedPagination.value,
      // });

      if (!!selectedGroupField.value && refQuickFilter.value) {
        refQuickFilter.value?.querySummary();
        return;
      }
      execQuery();
    };

    let proxyThis = {
      // displayColumns: computed(() => {
      //   return mOpts?.value?.visibleColumns;
      // }).value,
      // sortColumns: computed(() => columnSortBy).value,
      // ShowAutoFilterRow: showAutoFilterRow,
      options: { columns: props.optColumns },
      scheme: {},
      updateColumnsStyle(columns) {
        _.each(columns, (style, col) => {
          let colProfile = proxyThis.userProfile[col];
          proxyThis.userProfile[col] = { ...colProfile, ...style };
        });
        proxyThis.SetSchemeBase(proxyThis.scheme, proxyThis.userProfile);
        emitUpdateAdvQueryWithUserProfile();
        return proxyThis.userProfile;
      },
      updateColumnsWidth(columns) {
        _.each(columns, (width, col) => {
          let colProfile = proxyThis.userProfile[col];
          if (colProfile) {
            colProfile.width = width;
          } else {
            proxyThis.userProfile[col] = { width };
          }
        });
        proxyThis.updateUserProfile();
      },
      updateUserProfile(newUserProfile) {
        if (newUserProfile) {
          proxyThis.userProfile = newUserProfile;
        }
        let userProfile = proxyThis.userProfile;
        if (userProfile) {
          let root = refRoot.value;
          for (name in userProfile) {
            let th = root.querySelector(`tr th[data-field='${name}']`);
            if (th) {
              if (userProfile[name].width) {
                th.style.minWidth =
                  th.style.maxWidth =
                  th.style.width =
                    userProfile[name].width + 'px';

                if (props.isDev) {
                } else {
                  let col = _.find(columns.value, { field: name });
                  if (col && col.headerStyle) {
                    col.headerStyle = `min-width:${userProfile[name].width}px;max-width:${userProfile[name].width}px;width:${userProfile[name].width}px`;
                  }
                  if (col && col.optCol) {
                    col.optCol.width = `${userProfile[name].width}px`;
                  }
                }
              }
            }
          }
        }
      },
      SetSchemeBase(scheme, userProfile) {
        let displayColumns = scheme.displayColumns;
        proxyThis.snapshootUserProfile(userProfile);
        if (!displayColumns || displayColumns.length == 0) {
          displayColumns = _.filter(proxyThis.options.columns, {
            isShow: true,
          });
          displayColumns = _.map(displayColumns, col => {
            let newCol = {
              label: col.caption,
              value: col.dataField,
              width: col.width,
            };
            // if (col.width) {
            //   newCol.width = col.width;
            // }
            return newCol;
          });
          scheme.displayColumns = _.cloneDeep(displayColumns);
          scheme.sortColumns = [];
        }

        let playload = {
          sortColumns: scheme.sortColumns,
          displayColumns: displayColumns,
          userProfile,
        };
        if (scheme.pageSize || scheme.pageSize == 0) {
          proxyThis.PageSize = scheme.pageSize == 0 ? 10 : scheme.pageSize;
          mappingExpose.pageSize.value = proxyThis.PageSize;
        }
        if (_.has(scheme, 'showAutoFilterRow')) {
          showAutoFilterRow.value = scheme.showAutoFilterRow;
        }
        /*
        proxyThis.widgetInstance.clearFilter();
        if (proxyThis.skipWithRTFlag === true) {
          return;
        }
        proxyThis.ColumnConfigSubmitCB(playload);*/
        let visibleColumns = displayColumns.map(item => {
          return { name: item.value };
        });
        let sortColumns = _.map(
          _.sortBy(scheme.sortColumns, 'sortIndex'),
          item => {
            return { field: item.value, sort: item.sortOrder };
          },
        );

        proxyThis.snapshootSortColumns = [...sortColumns];

        columnSortByWithQueryPlan.value = sortColumns;

        proxyThis.updateUserProfile();
        if (proxyThis.userProfileSortColumns) {
          sortColumns = _.map(
            _.sortBy(proxyThis.userProfileSortColumns, 'sortIndex'),
            item => {
              return { field: item.value, sort: item.sortOrder };
            },
          );
        }

        onColumnSettingConfirm({
          visibleColumns: visibleColumns,
          sortColumns: sortColumns,
        });
      },
      snapshootSortColumns: [],
      ColumnConfigSubmitCB(playload) {
        let userProfile = playload.userProfile || proxyThis.userProfile;
        let userProfileSortColumns = {};
        proxyThis.sortColumns = playload.sortColumns;
        proxyThis.displayColumns = playload.displayColumns;
        proxyThis.sortColumnsSync = playload.sortColumns;
        proxyThis.displayColumnsSync = playload.displayColumns;
        let columnsInfo = _.map(playload.displayColumns, col => {
          let colWidth = col.width;
          if (userProfile) {
            let userProfileCol = userProfile[col.value];

            if (userProfileCol) {
              if (_.has(userProfileCol, 'width')) {
                colWidth = userProfileCol.width;
              }
              if (userProfileCol.sortOrder) {
                userProfileSortColumns[col.value] = userProfileCol;
              }
            }
          }

          return {
            ID: col.value,
            isShow: true,
            caption: col.label,
            dataField: col.value,
            width: colWidth,
          };
        });

        proxyThis.widgetInstance.clearSorting();
        if (false == _.isEmpty(userProfileSortColumns)) {
          _.each(userProfileSortColumns, (col, dataField) => {
            proxyThis.widgetInstance.columnOption(dataField, {
              sortIndex: col.sortIndex,
              sortOrder: col.sortOrder,
            });
            let sortCol = _.find(columnsInfo, { ID: dataField });
            if (sortCol) {
              sortCol.sortIndex = col.sortIndex;
              sortCol.sortOrder = col.sortOrder;
            }
          });
        } else {
          _.each(playload.sortColumns, (col, index) => {
            proxyThis.widgetInstance.columnOption(col.value, {
              sortIndex: col.sortIndex,
              sortOrder: col.sortOrder,
            });
            let sortCol = _.find(columnsInfo, { ID: col.value });
            if (sortCol) {
              sortCol.sortIndex = col.sortIndex;
              sortCol.sortOrder = col.sortOrder;
            }
          });
        }

        proxyThis.ColumnsInfo = {
          UseColumnContent: true,
          columnsInfo,
        };
        proxyThis.showColConf = false;
      },
      SetScheme(scheme, userProfile) {
        proxyThis.scheme = _.cloneDeep(scheme);
        proxyThis.SetSchemeBase(scheme, userProfile);
      },
      snapshootUserProfile(userProfile) {
        proxyThis.userProfile = userProfile;
        proxyThis.userProfileSortColumns = _.transform(
          proxyThis.userProfile,
          (result, val, key) => {
            if (val.sortOrder) {
              result.push({ value: key, ...val });
            }
          },
          [],
        );
      },
      GetScheme() {
        let displayColumns = _.transform(
          bind.computedVisibleColumns.value,
          (r, col) => {
            let columnInfo = _.find(bind.computedColumns.value, { name: col });
            if (columnInfo) {
              r.push({ label: columnInfo.label, value: columnInfo.name });
            }
          },
          [],
        );

        let sortColumns = _.transform(
          columnSortByWithQueryPlan.value,
          (r, sortCol, index) => {
            let columnInfo = _.find(bind.computedColumns.value, {
              name: sortCol.field,
            });
            if (columnInfo) {
              r.push({
                label: columnInfo.label,
                value: columnInfo.name,
                sortOrder: sortCol.sort,
                sortIndex: index,
              });
            }
          },
          [],
        );

        // {"id":"9ba0193a-62fc-29e2-1c85-d786d75a0a33","value":"AssignTo","label":"指派给","sortOrder":"desc","sortIndex":0}

        let valueValue = {
          // pageSize: proxyThis.PageSize,
          // pageSize: props.pageSize || proxyThis.scheme.pageSize || 0,
          pageSize:
            mappingExpose.pageSize.value ||
            props.pageSize ||
            proxyThis.scheme.pageSize ||
            0,
          showAutoFilterRow: showAutoFilterRow.value,
          displayColumns: displayColumns,
          sortColumns: sortColumns,
          // displayColumns: proxyThis.displayColumnsSync,
          // sortColumns: proxyThis.sortColumnsSync,
        };
        proxyThis.scheme = valueValue;
        return valueValue;
      },
      GetUserProfile() {
        let root = refRoot.value;
        let rootRect = root.getBoundingClientRect();
        if (rootRect.width == 0 && rootRect.height == 0) {
          /** 处理popup打开元素不可见是获取不到宽度，卡片关闭时列表宽度问题 */
          return proxyThis.userProfile;
        }
        let valueValue = _.transform(
          wrapVisibleColumns.value,
          (result, dataField) => {
            let col = wrapColumns.value.find(item => item.name == dataField);
            if (col && col.optCol) {
              result[dataField] = {};
              let th = root.querySelector(`tr th[data-field='${dataField}']`);
              if (th) {
                let width = th.getBoundingClientRect().width;
                result[dataField].width = width;
                col.headerStyle = `min-width:${width}px;max-width:${width}px;width:${width}px`;
              }
              if (columnKeys.value[dataField]) {
                result[dataField].sortIndex = columnKeys.value[dataField].index;
                result[dataField].sortOrder = columnKeys.value[dataField].sort;
              }
            }
          },
          {},
        );

        proxyThis.snapshootUserProfile(valueValue);
        return valueValue;
      },
    };
    const isSelectedRow = computed(() => {
      return selected?.value?.length > 0;
    });
    const rowClickArgs = ref();
    const refH = ref(0);
    const refreshHeight = () => {
      refH.value++;
    };

    const refreshHeightWithQuickGroup = () => {
      // console.log(refComponent.value);
      // refreshHeight();
      // return quickGroupHeight.value;
    };

    const MASK_FIX = '_mask';
    const ORIG_FIX = '_orig';
    const MASK_State = '_maskState';

    const quickGroupHeight = ref(0);

    const maskMethod = {
      computedMaskColumns: computed(() => {
        return _.filter(mappingProps.optColumns, col => {
          return true === col.enableMask;
        });
      }),
      computedMaskFields: computed(() => {
        return _.map(maskMethod.computedMaskColumns.value, 'dataField');
      }),
      EnableMask: EnableMask,
      showMask(show = true) {
        if (
          Funcs.HasMaskAuth &&
          Funcs.HasMaskAuth() &&
          Funcs.EnableMask &&
          Funcs.EnableMask()
        ) {
          EnableMask.value = show;
          _.each(props.rows, row => {
            maskMethod.showMaskByRow(row, show);
          });
        }
      },
      syncMaskOrig() {
        if (
          Funcs.HasMaskAuth &&
          Funcs.HasMaskAuth() &&
          Funcs.EnableMask &&
          Funcs.EnableMask()
        ) {
          _.each(maskMethod.computedMaskFields.value, field => {
            _.each(props.rows, row => {
              if (!row[`${field}${ORIG_FIX}`]) {
                row[`${field}${ORIG_FIX}`] = row[field];
              }
              row[MASK_State] = row[field] == row[`${field}${MASK_FIX}`];
            });
          });
        }
      },
      showMaskByRow(row, show) {
        show = _.isNil(show) ? !row[MASK_State] : show;
        if (
          Funcs.HasMaskAuth &&
          Funcs.HasMaskAuth() &&
          Funcs.EnableMask &&
          Funcs.EnableMask()
        ) {
          _.each(maskMethod.computedMaskFields.value, field => {
            if (!row[`${field}${ORIG_FIX}`]) {
              row[`${field}${ORIG_FIX}`] = row[field];
            }

            if (show) {
              row[field] = row[`${field}${MASK_FIX}`];
            } else {
              row[field] = row[`${field}${ORIG_FIX}`];
            }
            row[MASK_State] = show;
          });
        }
        return row;
      },
      isMasked: computed(() => EnableMask.value),

      /** 兼容老版本API */
      IsMasked: computed(() => EnableMask.value),
      ShowMaskByRow(row, show) {
        maskMethod.showMaskByRow(row, show);
      },
      ShowMask(show = true) {
        maskMethod.showMask(show);
      },
      /** 兼容老版本API */
    };

    const publicMethod = {
      setMultiHeader(headerConf) {
        mappingProps.headers = headerConf;
      },
      /** QuickFilter PublicMethod */
      getGroupByFilter(advancedFilter) {
        return refQuickFilter.value
          ? refQuickFilter.value?.getGroupByFilter(advancedFilter)
          : advancedFilter;
      },
      wrapSummary: (quickItemSummaryRaw, Cnt) => {
        return refQuickFilter.value?.wrapSummary(quickItemSummaryRaw, Cnt);
      },
      getSummaryFields: () => {
        return refQuickFilter.value?.getSummaryFields();
      },
      getSummaryFilter(advancedFilter = null) {
        return refQuickFilter.value
          ? refQuickFilter.value?.zipFasDynamicFilter(
              {},
              JSON.parse(publicMethod.getGroupByFilter(advancedFilter)).Filters,
            )
          : advancedFilter;
      },
      setFilters(filters) {
        return refQuickFilter.value
          ? refQuickFilter.value?.setFilters(filters)
          : filters;
      },
      getFilters(filters) {
        return refQuickFilter.value
          ? refQuickFilter.value?.getFilters(filters)
          : filters;
      },
      mergeFiltersBase(target = {}, ...sArgs) {
        return mergeFiltersBase(target, ...sArgs);
      },
      mergeFilters(target = {}, ...sArgs) {
        return mergeFilters(target, ...sArgs);
      },
      setSelectedItem(obj) {
        refQuickFilter.value?.setSelectedItem(obj);
      },
      updateByFilter(w) {
        refQuickFilter.value?.updateByFilter(w);
      },
      statisticalQuery() {
        publicMethod.querySummary();
      },
      querySummary() {
        refQuickFilter.value
          ? refQuickFilter.value.statisticalQuery()
          : execQuery();
      },
      getFasDynamicFilter(filters) {
        return refQuickFilter.value
          ? refQuickFilter.value?.getFasDynamicFilter(filters)
          : zipFasDynamicFilter({}, filters);
      },
      getFasDynamicGroupByFilter(advancedFilter) {
        return refQuickFilter.value
          ? refQuickFilter.value?.getFasDynamicGroupByFilter(advancedFilter)
          : zipFasDynamicFilter({}, advancedFilter);
      },
      getSummaryFields() {
        return refQuickFilter.value
          ? refQuickFilter.value?.getSummaryFields()
          : '';
      },
      /** QuickFilter PublicMethod */
    };

    const quickGroupPubMethod = {
      quickGroup: computed(() => {
        return refQuickFilter.value || publicMethod;
      }),
      setFilters: filters => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.setFilters(filters);
      },
      getFilters: filters => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.getFilters(filters);
      },
      mergeFiltersBase(target = {}, ...sArgs) {
        return publicMethod.mergeFiltersBase(target, ...sArgs);
      },
      mergeFilters(target = {}, ...sArgs) {
        return publicMethod.mergeFilters(target, ...sArgs);
      },
      getGroupByFilters: advancedFilter => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.getGroupByFilter(advancedFilter);
      },
      getFasDynamicFilter: filters => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.getFasDynamicFilter(filters);
      },
      getFasDynamicGroupByFilter: advancedFilter => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.getFasDynamicGroupByFilter(advancedFilter);
      },
      getSummaryFields: filters => {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        return quickGroup.getSummaryFields(filters);
      },
      statisticalQuery() {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        quickGroup.statisticalQuery();
      },
      querySummary() {
        let quickGroup = quickGroupPubMethod.quickGroup.value;
        quickGroup.querySummary();
      },
    };

    function findIndexByKey(row) {
      return _.findIndex(computedRows?.value, eachItem => {
        return eachItem[mappingProps.rowKey] == row[mappingProps.rowKey];
      });
    }

    const [mappingProps, mappingExpose] = useMappingProps(props, {
      scrollDeadZoneRightMode,
      updateColumnsStyle: proxyThis.updateColumnsStyle,
      updateColumnsWidth: proxyThis.updateColumnsWidth,
      updateUserProfile: proxyThis.updateUserProfile,
      cellClickInfo: {},
      selectMode: toRef(props, 'selection'),
      selected,
      columns: null,
      getVisibleColumns: () => {
        return wrapColumns.value
          .filter(col => {
            return wrapVisibleColumns.value.includes(col?.name);
          })
          .map(col => col?.name);
      },
      refreshHeight,
      mixinsSetHeight: refreshHeight,
      showAutoFilterRow,
      selectedRows: selected,
      selectedRow: computed(() =>
        selected.value.length > 0 ? selected.value[0] : undefined,
      ),
      rows: computed(() => computedRows.value),
      rowClickArgs,
      query: query,
      refresh: query,
      isSelectedRow: isSelectedRow,
      clearSelection: function () {
        selected.value = [];
      },
      selectRowsBy: function (obj) {
        // if ('multiple' == mappingExpose.selectMode) {

        // }
        if (obj) {
          selected.value = _.filter(wrapRows.value, eachItem => {
            return eachItem[mappingProps.rowKey] == obj[mappingProps.rowKey];
          });
        } else {
          // selected.value = [];
          mappingExpose.clearSelection();
        }
      },
      selectRowsByIndexes: function (indexes) {
        debugger;
        if (indexes) {
          selected.value = _.filter(wrapRows.value, (value, index) => {
            return indexes.includes(index);
          });
        } else {
          // selected.value = [];
          mappingExpose.clearSelection();
        }
      },
      columnsInfo: computed(() => {
        return wrapColumns?.value;
      }),
      selectedRowIndex: computed(() => {
        let i = -1;
        if (selected?.value?.length > 0) {
          i = findIndexByKey(selected?.value[0]);
        }
        return i;
      }),
      selectedRowIndexes: computed(() => {
        return _.map(selected?.value, row => findIndexByKey(row));
      }),
      SetScheme: proxyThis.SetScheme,
      GetScheme: proxyThis.GetScheme,
      GetUserProfile: proxyThis.GetUserProfile,
      // height: computed(() => {
      //   return height?.value;
      // }),
      pageIndex: ref(props.pageIndex),
      pageSize: ref(props.pageSize),
      checkOverflow() {
        refComponent?.value?.$el.querySelectorAll('td,th').forEach(td => {
          let sortIcon = '';
          if (td.classList.contains('sorted')) {
            sortIcon = '( ↑ )';
          }
          if (td.classList.contains('sort-desc')) {
            sortIcon = '( ↓ )';
          }
          td.setAttribute(
            'title',
            td.scrollWidth > td.clientWidth
              ? td.innerText.replace('arrow_upward', sortIcon)
              : '',
          );
        });
      },
      setMultiHeader: publicMethod.setMultiHeader,
      ...quickGroupPubMethod,
      /** QuickFilter PublicMethod */
      // quickGroup: computed(() => {
      //   return refQuickFilter.value || publicMethod;
      // }),
      // fasDynamicFilter: publicMethod.fasDynamicFilter,
      // fasDynamicSort: publicMethod.fasDynamicSort,
      /** QuickFilter PublicMethod */

      /** 掩码功能 */
      ...maskMethod,
      /** 掩码功能 */
      setFixedColumn,
    });

    const h = computed(() => {
      // const {
      //   getScrollTarget,
      //   getVerticalScrollPosition,
      //   setVerticalScrollPosition,
      // } = scroll;
      // let scrollTargetDomElement = getScrollTarget(window.body);
      // let os = getVerticalScrollPosition(scrollTargetDomElement);
      // console.log(os);
      let top = refComponent.value?.$el
        ? dom.offset(refComponent.value?.$el).top
        : 0;

      if (props.isDev) {
        let designPage = document.querySelector('#app > div.design-page');
        if (designPage && designPage.scrollTop) {
          top += designPage.scrollTop;
        }
      } else {
        if (document.scrollingElement.scrollTop > 0) {
          top += document.scrollingElement.scrollTop;
        }
      }

      const simplePagingOffset = mappingProps.simplePaging ? 50 : 0;

      return (
        $q.screen.height - top + (refH.value - refH.value) - simplePagingOffset
      );
    });

    const height = computed(() => {
      let isAuto =
        mappingProps.fillMode == 'auto' ||
        ['auto', 'fill'].includes(
          (mappingProps.height || '').trim().toLowerCase(),
        );
      let mb = mappingProps.fillMarginBottom || '0px';
      let hValue = h.value <= 0 ? mappingProps.height || undefined : h.value;
      scrollHover();
      return isAuto
        ? `calc(${hValue - parseInt(mb) - 50 - (quickGroupHeight?.value || 0)}px)`
        : mappingProps.height || undefined;
    });

    const computedDynamicMinHeight = computed(() => {
      return mappingProps.dynamicMinHeight < C.dynamicMinHeight
        ? C.dynamicMinHeight
        : mappingProps.dynamicMinHeight;
    });

    const showFixedHeader = computed(() => {
      // return isDynamicFillMode.value
      return mappingProps.fixedHeader;
    });

    const computedStyle = computed(() => {
      return isDynamicFillMode.value
        ? {
            ...(wrapRows.value.length === 0 && {
              minHeight: `${computedDynamicMinHeight.value}px`,
            }),
          }
        : {
            height: height.value,
            minHeight: '200px',
          };
    });

    const quickGroupShow = computed(() => {
      return props.enableGrouping && mappingProps.isGrouping;
    });

    const selectedGroupField = ref('');
    const selectedGroupFieldSort = ref('CD');
    const selectSortPopupRef = ref();

    const selectedGroupFieldSortItems = ref([
      { text: $q.lang.dataGrid?.countDesc || '数量( ↓ )', value: 'CD' },
      { text: $q.lang.dataGrid?.countAsc || '数量( ↑ )', value: 'CA' },
      { text: $q.lang.dataGrid?.nameDesc || '名称( ↓ )', value: 'ND' },
      { text: $q.lang.dataGrid?.nameAsc || '名称( ↑ )', value: 'NA' },
    ]);
    const sortMapping = {
      NA: ['label', 'asc'],
      ND: ['label', 'desc'],
      CA: ['Total', 'asc'],
      CD: ['Total', 'desc'],
    };
    const quickGroupMoreShow = computed(() => {
      return (
        selectedGroupField.value.caption &&
        (isOverflow.value || isOverflowFlag.value)
      );
    });

    watch(
      () => h.value,
      (newVal, oldVal) => {
        quickGroupHeight.value = 0;
      },
    );
    watch(
      () => [quickGroupShow.value, quickGroupMoreShow.value],
      () => {
        if (mappingExpose.isGrouping) {
          quickGroupHeight.value = calcQuickGroupHeight();
        } else {
          quickGroupHeight.value = 0;
        }
      },
    );

    const calcQuickGroupHeight = () => {
      let h = 0;
      const paddingTop = 12;
      if (quickGroupShow.value) {
        h = 24 + paddingTop;
        if (quickGroupMoreShow.value) {
          h = 56 + paddingTop;
        }
      }
      return h;
    };

    // quickGroupHeight = computed(calcQuickGroupHeight);

    const {
      columns,
      cellSlot,
      computedPagination,
      rowNumberColumn,
      stickyCmdColumn,
      // computedVisibleColumns,
      ...bind
    } = useDataGridOpts(mappingProps, attrs, emit, expose, slots, {
      bodyCellLink,
      bodyCellEnum,
      bodyCellBoolean,
      bodyCellDate,
      bodyCellCustomContent,
      bodyCellCharts,
    });
    mappingExpose.columns = columns;
    // mappingExpose.pageIndex = computed(() => {
    //   return computedPagination?.value.page;
    // });
    // mappingExpose.pageSize = computed(() => {
    //   return +computedPagination?.value.rowsPerPage;
    // });
    let { page, rowsPerPage, sortBy, descending } = computedPagination.value;

    let filter = {};
    let filterByColumn = {};
    columns.value.forEach(col => {
      if (col.field) {
        filter[col.field] = {
          ...useOperationProps.operation.default(),
          dataType: col?.optCol?.dataType,
          col: col,
        };
        filterByColumn[col.field] = { col };
      }
    });

    const mockRows = computed(() => {
      let rows = [];
      for (let index = 1; index <= 30; index++) {
        rows.push(
          zipObject(
            bind.computedColumns.value.map(item => item.name),
            bind.computedColumns.value.map(item => `${item.name}_${index}`),
          ),
        );
      }
      return rows;
    });

    const reactiveFilter = reactive(filter);

    const mOpts = useOpts(bind);

    const onRequest = requestProp => {
      let isRowsPerPageChange =
        computedPagination.value.rowsPerPage !=
        requestProp.pagination.rowsPerPage;

      let pageChange =
        computedPagination.value.page != requestProp.pagination.page ||
        isRowsPerPageChange;

      mappingExpose.pageIndex.value = requestProp.pagination.page;
      mappingExpose.pageSize.value = requestProp.pagination.rowsPerPage;

      const filter = props.filter;
      if (pageChange) {
        nextTick(() => {
          emit('request', {
            pagination: requestProp.pagination,
            filter: requestProp.filter || props.filter,
            getCellValue,
          });
          if (isRowsPerPageChange) {
            emitUpdateAdvQueryWithPageSizeChange();
          }
        });
      } else {
      }
      computedPagination.value.sortBy = requestProp.pagination.sortBy;
      computedPagination.value.descending = requestProp.pagination.descending;
    };

    // mappingExpose.columns = columns;
    // mappingExpose.rows = computedRows.value;
    mappingExpose.height = computed({
      get: () => {
        return height?.value;
      },
      set: val => {
        mappingProps.height = val;
      },
    });
    expose(mappingExpose);
    let resizingColumn = null;
    let startX = null;
    let width = null;
    const startResize = (p, event) => {
      // resizingColumn.value = index;
      resizingColumn = p.col;
      startX = event.pageX;
      const th = event.srcElement.closest('th');
      width = dom.width(th);
      console.log('resizeColumn', 'startResize', event.pageX);
    };
    const resizeColumn = event => {
      if (resizingColumn === null) return;

      const delta = event.pageX - startX;
      const newWidth = width + delta;

      console.log(
        'resizeColumn',
        resizingColumn,
        delta,
        startX,
        event.pageX,
        newWidth,
      );

      if (newWidth > 50) {
        const th = event.srcElement.closest('th');
        // columns[resizingColumn.value].width = newWidth;
        th.style.width = `${newWidth}px`;
        // th.style.width = `500px`;
        // startX = event.pageX;
      }
    };
    const stopResize = () => {
      console.log('resizeColumn', 'stopResize');
      resizingColumn = null;
      startX = null;
    };

    watch(
      () => mappingProps.selection,
      val => {
        selected.value = [];
        nextTick(() => {
          setFixedColumn({ forceLeft: true });
        });
      },
    );

    const debuggerInfo = () => {
      return (
        <div style='color:red;'>
          <div>
            wrapColumns.value {wrapColumns.value.map(item => item.name).join()}
          </div>
          <div>
            wrapVisibleColumns.value {JSON.stringify(wrapVisibleColumns.value)}
          </div>
          <div>pageSizeRange.value {JSON.stringify(pageSizeRange.value)} </div>

          <TBtn
            onClick={() => {
              updateVisibleColumns(['UserName', 'Alias', 'Account']);
            }}
          >
            UserName,Alias,Account
          </TBtn>
          <TBtn
            onClick={() => {
              updateVisibleColumns(['Alias', 'UserName', 'Account']);
            }}
          >
            Alias,UserName,Account
          </TBtn>
          <TBtn
            onClick={() => {
              updateVisibleColumns(['Account', 'Alias', 'UserName']);
            }}
          >
            Account,Alias,UserName
          </TBtn>
        </div>
      );
    };

    let localTd = null;
    function mouseDown(e) {
      // 记录单元格
      if (!(e && e.target)) return;
      localTd = e.target;
      localTd.isColMove = false;
      if (e.offsetX > localTd.offsetWidth - 10) {
        localTd.mouseDown = true;
        localTd.oldX = e.x;
        localTd.oldWidth = localTd.offsetWidth;
      }
    }

    function mouseMove_sync_col_width(e) {
      if (!(e && e.target)) return;
      const vm = e.target;
      // 更改鼠标样式

      if (vm.tagName != 'TH') {
        return;
      }

      if (e.offsetX > vm.offsetWidth - 10) {
        vm.style.cursor = 'col-resize';
        vm.isColMove = true;
      } else {
        vm.style.cursor = 'default';
      }

      // console.log('mouseMove', e.offsetX, vm.offsetWidth, e.offsetX > vm.offsetWidth - 10, vm.style.cursor, vm)

      // 取出暂存的Table Cell
      if (!localTd) localTd = vm;
      if (localTd.mouseDown !== null && localTd.mouseDown === true) {
        localTd.style.cursor = 'default';
        if (localTd.oldWidth + (e.x - localTd.oldX) > 0) {
          // localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          // localTd.style.maxWidth =
          //   localTd.style.minWidth =
          //   localTd.style.width =
          //     `${localTd.width}px`;
        }
        // 调整列宽
        // localTd.style.maxWidth =
        //   localTd.style.minWidth =
        //   localTd.style.width =
        //     localTd.width;
        localTd.style.cursor = 'col-resize';

        let rect = localTd.getBoundingClientRect();
        if (rect.width != localTd.width) {
          // localTd.style.cursor = 'no-drop';
        }

        const field = localTd.getAttribute('data-field');
        const fieldCol = mappingColumns.value[field];
        if (fieldCol) {
          fieldCol.width = localTd.width;
        }

        setFixedColumn({ forceLeft: true });
      }
    }

    function mouseMove(e) {
      if (!(e && e.target)) return;
      const vm = e.target;
      // 更改鼠标样式

      if (vm.tagName != 'TH') {
        return;
      }

      if (e.offsetX > vm.offsetWidth - 10) {
        vm.style.cursor = 'col-resize';
        vm.isColMove = true;
      } else {
        vm.style.cursor = 'default';
      }

      // console.log('mouseMove', e.offsetX, vm.offsetWidth, e.offsetX > vm.offsetWidth - 10, vm.style.cursor, vm)

      // 取出暂存的Table Cell
      if (!localTd) localTd = vm;
      if (localTd.mouseDown !== null && localTd.mouseDown === true) {
        localTd.style.cursor = 'default';
        if (localTd.oldWidth + (e.x - localTd.oldX) > 0) {
          // localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          localTd.width = localTd.oldWidth + (e.x - localTd.oldX);
          localTd.style.maxWidth =
            localTd.style.minWidth =
            localTd.style.width =
              `${localTd.width}px`;
        }
        // 调整列宽
        localTd.style.maxWidth =
          localTd.style.minWidth =
          localTd.style.width =
            localTd.width;
        localTd.style.cursor = 'col-resize';

        let rect = localTd.getBoundingClientRect();
        if (rect.width != localTd.width) {
          // localTd.style.cursor = 'no-drop';
        }
        setFixedColumn({ forceLeft: true });
        // 调整该列中的每个Cell
        let table = localTd;
        // while (table.tagName !== 'TABLE') table = table.parentElement;
        // for (let j = 0; j < table.rows.length; j++) {
        //   table.rows[j].cells[localTd.cellIndex].width = localTd.width;
        // }
      }
    }

    function mouseUp(e, col) {
      // 结束宽度调整
      if (!(e && e.target)) return;
      if (!localTd) localTd = e.target;
      localTd.mouseDown = false;
      localTd.style.cursor = 'default';

      let dField = localTd.getAttribute('data-field');
      if (dField && col && e.button == 0) {
        setTimeout(() => {
          /** 等待排序逻辑一并提交 */
          emitUpdateAdvQueryWithUserProfile();
          setFixedColumn({ forceLeft: true });
        }, 10);
      }
    }

    const emitUpdateAdvQueryWithUserProfile = () => {
      mappingExpose.checkOverflow();
      emit('UpdateAdvQueryWithUserProfile');
    };

    const emitUpdateAdvQueryWithResetSort = () => {
      emit('UpdateAdvQueryWithResetSort');
    };

    const emitUpdateAdvQueryWithPageSizeChange = () => {
      emit('UpdateAdvQueryWithPageSizeChange');
    };

    watch(
      () => mappingProps.allowSort,
      val => {
        columnSortBy.length = 0;
      },
    );

    function onThClickHandler(e, { col }) {
      let item = _.find(columnSortBy, { field: col.field });
      if (item) {
        if (item.sort == 'asc') {
          item.sort = 'desc';
        } else if (item.sort == 'desc' && !e.shiftKey) {
          _.remove(columnSortBy, item);
          return;
        } else {
          item.sort = 'asc';
        }
      } else {
        item = { field: col.field, sort: 'asc' };
        if (e.shiftKey) {
          columnSortBy.push(item);
        } else {
          columnSortBy.length = 0;
          columnSortBy.push(item);
        }
      }
    }

    function menuSetSort(e, { col }, sort) {
      let item = _.find(columnSortBy, { field: col.field });
      if (item) {
        item.sort = sort;
      } else {
        item = { field: col.field, sort: sort };
        if (e.shiftKey) {
          columnSortBy.push(item);
        } else {
          columnSortBy.length = 0;
          columnSortBy.push(item);
        }
      }
    }

    function sortIcon(props) {
      return (
        <>
          <TIcon
            name='arrow_upward'
            style='pointer-events: none;margin-top: -3px;'
            class='q-table__sort-icon q-table__sort-icon--center'
          />
          {columnSortBy.length > 1 &&
            columnKeys.value[props.col.field] &&
            columnKeys.value[props.col.field]?.index + 1}
        </>
      );
    }

    const propsSize = ref(props.pageSize);
    watch(
      () => {
        return props.pageSize;
      },
      val => {
        if (false === pageSizeRange.value.includes(val)) {
          propsSize.value = val;
        }
      },
    );

    const pageSizeRange = computed(() => {
      let returnValue = [10, 20, 50, 100, 150, 500, 1000];
      let pSize = propsSize.value;
      if (false == returnValue.includes(+pSize)) {
        returnValue.push(pSize);
        returnValue = _.uniq(returnValue);
        returnValue = _.sortBy(returnValue);
      }
      return returnValue;
    });

    function onRowClickHandler(evt, row, index) {
      debugger;
      rowClickArgs.value = { data: row, rowIndex: index };
      emit('row_click');
    }

    function onSelectionHandler(newSelected) {
      selected.value = newSelected;
      emit('selectionChanged');
    }
    let isFirst = false;
    watch(
      () => mappingProps.rows,
      () => {
        if (!isFirst) {
          maskMethod.showMask();
        } else {
          maskMethod.showMask(maskMethod.isMasked.value);
        }
        isFirst = true;
        let vColKeys = _.map(proxyThis.scheme.displayColumns, 'value');
        if (vColKeys.length > 0) {
          updateVisibleColumns(vColKeys);
        }
        setTimeout(() => {
          emit('dataSourceLoaded');
        });
        setTimeout(() => {
          setFixedColumn();
          if (showFixedHeader.value && refHeader.value) {
            refreshHeaderLayout(refHeader.value, refRoot.value);
          }
        }, 500);
      },
    );
    watch(
      () => computedPagination.value.page,
      () => {
        emit('pageChange');
      },
    );
    watch(
      () => computedPagination.value.rowsPerPage,
      () => {
        emit('pageSizeChange');
      },
    );

    const updateVisibleColumns = vColKeys => {
      console.log('FFFF', vColKeys.join(','));
      vColKeys = _.uniq(vColKeys);

      let newVisibleColumns = [];
      _.each(vColKeys, item => {
        let a = _.find(columns.value, { name: item });
        if (a) newVisibleColumns.push(a);
      });

      let remove = _.remove(columns.value, col => vColKeys.includes(col?.name));
      let stickyCmdColumn = _.find(columns.value, {
        name: 'stickyCmdColumn',
      });
      let stickyCmdColumnIndex = _.findIndex(columns.value, stickyCmdColumn);

      if (bind.computedVisibleColumns.value.includes('stickyCmdColumn')) {
        if (false == vColKeys.includes('stickyCmdColumn'))
          vColKeys.push('stickyCmdColumn');
      }
      let hasRowNumberColumn = 0;
      if (bind.computedVisibleColumns.value.includes('rowNumberColumn')) {
        if (false == vColKeys.includes('rowNumberColumn'))
          vColKeys.push('rowNumberColumn');
        hasRowNumberColumn = 1;
      }

      bind.computedVisibleColumns.value = _.uniq(vColKeys);

      if (stickyCmdColumn && stickyCmdColumn.classes.includes('left')) {
        columns.value.splice(
          stickyCmdColumnIndex + hasRowNumberColumn + 1,
          0,
          ...newVisibleColumns,
        );
      } else {
        columns.value.splice(
          stickyCmdColumnIndex + hasRowNumberColumn,
          0,
          ...newVisibleColumns,
        );
      }

      proxyThis.updateUserProfile();
    };

    const onColumnSettingConfirm = ({ visibleColumns, sortColumns }) => {
      let vColKeys = _.map(visibleColumns, 'name');
      updateVisibleColumns(vColKeys);

      columnSortBy.length = 0;
      columnSortBy.push(...sortColumns);

      twoWayProps.showPopupColumnsSetting.value = false;
    };

    const onColumnSettingConfirmWithQueryPlan = ({
      visibleColumns,
      sortColumns,
    }) => {
      debugger;
      let vColKeys = _.map(visibleColumns, 'name');
      updateVisibleColumns(vColKeys);

      columnSortByWithQueryPlan.value = sortColumns;

      twoWayProps.showPopupColumnsSetting.value = false;
    };

    const renderPopupColumnSetting = () => {
      return (
        <QDialog
          persistent-
          maximized
          v-model={
            twoWayProps.showPopupColumnsSetting.value
          } /** t层 组件此刻不兼容这个模式，留着是为了后续组件支持 */
          v-model:show={twoWayProps.showPopupColumnsSetting.value}
          position='right'
          transition-show='slide-left'
          transition-hide='slide-right'
        >
          <TCard>
            <ColumnSetting
              lockTab={isMultiMeader.value ? 'sort' : ''}
              columnSortBy={columnSortByWithQueryPlan.value}
              visibleColumns={bind.computedVisibleColumns.value}
              columns={columns.value}
              onCancel={() =>
                (twoWayProps.showPopupColumnsSetting.value = false)
              }
              onConfirm={eArgs => {
                onColumnSettingConfirmWithQueryPlan(eArgs);
                emit('UpdateAdvQuery');
              }}
            ></ColumnSetting>
          </TCard>
        </QDialog>
      );
    };

    const wrapMockData = computed(() => {
      if (typeof props.mockData == 'string') {
        return JSON.parse(props.mockData);
      } else {
        return props.mockData;
      }
    });

    const wrapColumns = computed(() => {
      console.log('wrapColumns');
      if (props.isDev) {
        if (props.optColumns?.length > 0) {
          return columns.value;
        } else {
          let rowNumberColumn = columns?.value?.find(
            item => item.name == 'rowNumberColumn',
          );
          let stickyCmdColumn = columns?.value?.find(
            item => item.name == 'stickyCmdColumn',
          );
          let cols = _.map(wrapMockData.value.columns, item => {
            return { name: item.field, ...item, __isShow: true };
          });
          return [
            props.showRowNumber &&
              rowNumberColumn && { ...rowNumberColumn, __isShow: true },
            // rowNumberColumn ? { ...rowNumberColumn, __isShow: true } : null,
            ...cols,
            props.enableCmdCol &&
              stickyCmdColumn && { ...stickyCmdColumn, __isShow: true },
            // stickyCmdColumn ? { ...stickyCmdColumn, __isShow: true } : null
          ].filter(item => item);
        }
      } else {

        if (computedHeaders.value.header?.length > 0) {
          let s = computedHeaders.value.header.map(item => {
            return columns.value.find(col => col.name == item);
          });
          return s;
        }
        return columns.value;
      }
    });

    const wrapVisibleColumns = computed(() => {
      console.log('wrapColumns', 'wrapVisibleColumns');
      if (props.isDev) {
        return [
          props.showRowNumber && 'rowNumberColumn',
          ..._.map(_.filter(wrapColumns.value, '__isShow'), 'name'),
          props.enableCmdCol && 'stickyCmdColumn',
        ];
      } else {
        return mOpts.value.visibleColumns;
      }
    });

    const wrapRows = computed(() => {
      console.log('wrapColumns', 'wrapRows');
      mappingExpose?.clearSelection();
      setTimeout(() => {
        mappingExpose?.checkOverflow();
      }, 500);

      if (props.isDev) {
        if (props.optColumns?.length > 0) {
          return mockRows.value;
        } else {
          return wrapMockData.value.rows;
        }
      } else {
        if (props.showRowNumber) {
          return computedRows.value.map((row, i) => ({
            ...row,
            _rowNumber: i + (props.pageIndex - 1) * props.pageSize,
          }));
        } else {
          return computedRows.value;
        }
      }
    });

    const clearSort = col => {
      let findIndex = columnSortBy.findIndex(item => {
        return item.field == col.field;
      });
      if (findIndex > -1) {
        columnSortBy.splice(findIndex, 1);
      }
      emitUpdateAdvQueryWithUserProfile();
    };

    const sortReset = () => {
      columnSortBy.length = 0;
      emitUpdateAdvQueryWithResetSort();
    };

    const headerCellSlot = (props, extProps) => {
      let unsortable = ['stickyCmdColumn'];
      let isSortable = false === unsortable.includes(props.col.name);
      return (
        <TTh
          class={[
            isSortable && 'sortable',
            columnKeys.value[props.col.field] && 'sorted',
            columnKeys.value[props.col.field]?.sort == 'desc' && 'sort-desc',
          ]}
          {...extProps}
          style={{
            zIndex: 110,
            [props.col.width && 'min-width']: `${props.col.width}px`,
            [props.col.width && 'max-width']: `${props.col.width}px`,
            [props.col.width && 'width']: `${props.col.width}px`,
          }}
          props={props}
          data-field={props.col.field}
          onMousedown={mouseDown}
          onMousemove={
            mappingProps.allowColumnResizing && mouseMove_sync_col_width
          }
          // onMousemove={mouseMove}
          onMouseup={e => {
            mouseUp(e, props.col);
          }}
          onClick={
            mappingProps.allowSort &&
            function name(e) {
              if (e.target.isColMove) {
                /** 如果是调整列宽不处罚排序逻辑 */
                return;
              }
              onThClickHandler(e, props);
            }
          }
        >
          {isSortable && (
            <TMenu touch-position context-menu class={[styles.contextMenu]}>
              <TList>
                <TItem
                  class={[styles.contextMenuItem]}
                  clickable
                  v-close-popup
                  disable={columnKeys.value[props.col.field]?.sort == 'asc'}
                  onClick={e => menuSetSort(e, props, 'asc')}
                >
                  <TItemSection class='q-pr-none'>
                    <div class={[styles.contextMenuItemSection]}>
                      <div class={[styles.icon]}>
                        <TIcon
                          name='icon-t-sort-ascending'
                          // size='xs'
                        />
                      </div>
                      <div>{$q.lang.dataGrid?.sortAsc}</div>
                    </div>
                  </TItemSection>
                </TItem>
                <TItem
                  class={[styles.contextMenuItem]}
                  clickable
                  v-close-popup
                  disable={columnKeys.value[props.col.field]?.sort == 'desc'}
                  onClick={e => menuSetSort(e, props, 'desc')}
                >
                  <TItemSection class='q-pr-none'>
                    <div class={[styles.contextMenuItemSection]}>
                      <div class={[styles.icon]}>
                        <TIcon
                          name='icon-t-sort-descending'
                          // style='transform: scaleY(-1);'
                          // size='xs'
                        />
                      </div>
                      <div>{$q.lang.dataGrid?.sortDesc}</div>
                    </div>
                  </TItemSection>
                </TItem>
                <TItem
                  class={[styles.contextMenuItem]}
                  clickable
                  v-close-popup
                  disable={
                    columnSortBy.length == 0 ||
                    !columnKeys.value[props.col.field]?.sort
                  }
                  onClick={() => {
                    clearSort(props.col);
                    // columnSortBy.length = 0;
                  }}
                >
                  <TItemSection class='q-pr-none'>
                    <div class={[styles.contextMenuItemSection]}>
                      <div class={[styles.icon]}>
                        <TIcon />
                      </div>
                      <div>{$q.lang.dataGrid?.sortClear}</div>
                    </div>
                  </TItemSection>
                </TItem>
                <TItem
                  class={[styles.contextMenuItem]}
                  clickable
                  v-close-popup
                  onClick={() => {
                    sortReset();
                  }}
                >
                  <TItemSection class='q-pr-none'>
                    <div class={[styles.contextMenuItemSection]}>
                      <div class={[styles.icon]}>
                        <TIcon />
                      </div>
                      <div>{$q.lang.dataGrid?.sortReset}</div>
                    </div>
                  </TItemSection>
                </TItem>
              </TList>
            </TMenu>
          )}
          {isSortable &&
            mappingProps.allowSort &&
            props.col.align == 'right' &&
            sortIcon(props)}
          {props.col.label}
          {props.col.optCol &&
            props.col.optCol.hintConf &&
            props.col.optCol.hintConf.enable &&
            headerCellHint(props)}
          {isSortable &&
            mappingProps.allowSort &&
            props.col.align != 'right' &&
            sortIcon(props)}
        </TTh>
      );
    };
    const headerCell = () => {
      let slot = {
        headerCell: headerCellSlot,
      };
      if (props.isDev) {
        slot.headerCell;
      }
      return slot;
    };

    const classGridSimple = computed(() => {
      if (attrs?.class?.includes('tr-data-grid-simple')) {
        return {
          showStriped: false,
          separator: 'none',
          bordered: false,
        };
      } else {
        return {
          showStriped: mappingProps.showStriped,
        };
      }
    });

    const beforeContextmenu = evt => {
      emit('beforeContextMenuShow', evt);
    };

    const paginationSlot = scope => {
      return (
        <div>
          {scope.pagesNumber > 2 && (
            <QBtn
              icon='first_page'
              color='grey-8'
              round
              dense
              flat
              disable={scope.isFirstPage}
              onClick={scope.firstPage}
            />
          )}
          <QBtn
            icon='chevron_left'
            color='grey-8'
            round
            dense
            flat
            disable={scope.isFirstPage}
            onClick={scope.prevPage}
          />
          <QBtn
            icon='chevron_right'
            color='grey-8'
            round
            dense
            flat
            disable={scope.isLastPage}
            onClick={scope.nextPage}
          />
          {scope.pagesNumber > 2 && (
            <QBtn
              icon='first_page'
              color='grey-8'
              round
              dense
              flat
              disable={scope.isLastPage}
              onClick={scope.lastPage}
            />
          )}
        </div>
      );
    };

    const refQuickFilter = ref();

    function pickQuickFilterProps(mappingProps) {
      return pickProps(mappingProps, 'qfBind', '_QuickGroupFilter');
    }

    function mappingQuickFilterEvent(emit, emits) {
      return mappingEvent(emit, emits, '_QuickGroupFilter');
    }

    const groupingFilterVield = ref();
    const quickFilterEvent = mappingQuickFilterEvent(emit, TQuickFilter.emits);
    const groupFiledSerachValue = ref('');
    const groupingColumns = computed(() => {
      let groupColumns = _.filter(props.optColumns, { enabledGrouping: true });
      if (0 === groupColumns.length) {
        groupColumns = props.optColumns;
      }
      groupColumns = _.filter(groupColumns, item => {
        if (item.RefSchemaExpr && item.RefSchemaExpr.includes) {
          return false === item.RefSchemaExpr.includes('.__UserDefineColumns.');
        }
        return true;
      });
      return _.filter(groupColumns, c => {
        const serachValue = groupFiledSerachValue.value.trim();
        return serachValue == '' || c.caption.includes(serachValue);
      });
    });
    const selectRef = ref();
    const selectPopupRef = ref();
    const selectedGroupFieldSnapshot = ref('');
    watch(
      () => mappingProps.isGrouping,
      newValue => {
        if (false === newValue) {
          selectedGroupFieldSnapshot.value = selectedGroupField.value;
          clearSelectedGroupField(!!selectedGroupField.value);
          if (resizeObserver) {
            resizeObserver.disconnect();
          }
        } else {
          nextTick(() => {
            selectedGroupField.value = selectedGroupFieldSnapshot.value;
            if (refQuickFilter.value) {
              resizeObserver.observe(refQuickGroupDiv.value);
              resizeObserver.observe(refQuickFilter.value.$el);
            }
          });
        }
        nextTick(() => {
          refreshHeightWithQuickGroup();
        });
      },
    );
    watch(selectedGroupField, (newValue, oldValue) => {
      if (newValue) {
        filterField.value = {
          ...filterField.value,
          ...{
            dataType: newValue.dataType,

            tableCode: newValue.tableAlias || newValue.dataField,
            fieldCode: newValue.originalName || newValue.dataField,

            tableAlias: newValue.tableAlias,
            fieldAlias: newValue.dataField,
            fieldName: newValue.caption,
          },
        };
        onGroupInitHandler();
        isOverflow.value = isOverflowFlag.value = false;
      }
      emit('groupFieldChange', newValue);
    });
    const clearSelectedGroupField = (isQuery = false) => {
      filterField.value = {
        ...filterField.value,
        ...{
          dataType: '',

          tableCode: '',
          fieldCode: '',

          tableAlias: '',
          fieldAlias: '',
          fieldName: '',
        },
      };
      selectedGroupField.value = '';
      console.log('filterFields', filterFields.value);
      isQuery && nextTick(execQuery);
      nextTick(refreshHeightWithQuickGroup);
    };

    const refQuickGroupDiv = ref();
    const isOverflow = ref(false);
    const isOverflowFlag = ref(false);
    // const isOverflow = computed(() => {
    //   let { height } = refQuickGroupDiv.value?.getBoundingClientRect() || {};
    //   let { height2 } = refQuickFilter.value?.$el.getBoundingClientRect() || {};
    //   return height2 > height;
    // });

    const fillPopupWidth = () => {
      let { width } = document
        .querySelector('.grouping-filter-field-popup-content-class')
        .getBoundingClientRect();

      if (width) {
        document.querySelector(
          '.grouping-filter-field-selectPopup',
        ).style.width = width + 'px';
      }
    };

    const isDesktop = computed(() => {
      return !($q.screen.xs || $q.platform.is.mobile);
    });

    const renderQuickFilter = () => {
      let dynamicProps = pickQuickFilterProps(mappingProps);

      return (
        <>
          {/* {JSON.stringify(dynamicProps)} */}
          {/* {JSON.stringify(props.enableQuickFilter)} */}
          {/* {JSON.stringify(props.loading_GridData || props.loading_all)} */}
          {/* {props.enableGrouping && mappingProps.isGrouping && ( */}
          {quickGroupShow.value && (
            <div
              class={['grouping-filter-container']}
              style={{
                [mappingProps.loading && 'pointerEvents']: 'none',
                // pointerEvents: mappingProps.loading ? 'none' : 'initial',
              }}
            >
              <div class={['grouping-filter-title']} style=''>
                <div class='grouping-filter-title-container' style=''>
                  <span>{$q.lang.dataGrid?.quickGroup || '按'}</span>
                  <span
                    ref={groupingFilterVield}
                    class={['grouping-filter-field']}
                    style=''
                  >
                    <span>
                      {selectedGroupField.value.caption ||
                        $q.lang.dataGrid?.quickGroupChoice ||
                        '请选择'}
                      <q-popup-proxy
                        ref={selectPopupRef}
                        class={['grouping-filter-field-selectPopup']}
                        style=''
                        // target={groupingFilterVield.value}
                        onHide={() => {
                          // selectRef.value.hidePopup();
                        }}
                        onShow={() => {
                          selectRef.value.$el.addEventListener(
                            'click',
                            e => {
                              e.stopPropagation();
                            },
                            true,
                          );
                          selectRef.value.showPopup();
                        }}
                      >
                        <QSelect
                          ref={selectRef}
                          removeTabindex
                          popup-content-class='grouping-filter-field-popup-content-class'
                          class={['tr-select-small']}
                          dense
                          // outlined
                          use-input
                          v-model={selectedGroupField.value}
                          emit-value
                          map-options
                          // clearable
                          option-label='caption'
                          // option-value='dataField'
                          hide-input
                          fill-input
                          hide-selected
                          options-dense
                          hide-dropdown-icon
                          dropdown-icon={`${TComponents?.IconList?.common ?? 'fas dx-icon'} ${TComponents?.IconList?.arrowDown ?? 'icon-t-arrow-down'}`}
                          borderless={true}
                          options={groupingColumns.value}
                          onFilter={(value, doneFn) => {
                            groupFiledSerachValue.value = value;
                            doneFn();
                          }}
                          onPopupShow={() => {
                            setTimeout(fillPopupWidth, 10);
                            setTimeout(fillPopupWidth, 50);
                            setTimeout(fillPopupWidth, 100);
                            // selectRef.value.$el.style.width = width + 'px';
                          }}
                          onPopupHide={() => {
                            nextTick(() => {
                              selectPopupRef.value.hide();
                            });
                          }}
                        ></QSelect>
                      </q-popup-proxy>
                    </span>
                    {selectedGroupField.value.caption && (
                      <q-icon
                        class='cursor-pointer'
                        onClick={() => {
                          clearSelectedGroupField(true);
                          // selectedGroupField.value = '';
                        }}
                        name='clear'
                      />
                    )}
                  </span>
                  <span>
                    <span>{$q.lang.dataGrid?.quickGroupBy || '分组'}</span>
                  </span>
                  {selectedGroupField.value.caption &&
                    _.first(_.values(quickItems.value))?.length > 1 && (
                      <span class='grouping-filter-field' style=''>
                        {_.find(selectedGroupFieldSortItems.value, {
                          value: selectedGroupFieldSort.value,
                        })?.text || ''}
                        <q-popup-proxy ref={selectSortPopupRef}>
                          <TList dense bordered padding class='rounded-borders'>
                            {selectedGroupFieldSortItems.value.map(o => (
                              <TItem
                                clickable
                                v-ripple
                                onClick={() => {
                                  selectedGroupFieldSort.value = o.value;
                                  selectSortPopupRef.value.hide();
                                }}
                              >
                                <TItemSection>{o.text}</TItemSection>
                              </TItem>
                            ))}
                          </TList>
                        </q-popup-proxy>
                      </span>
                    )}
                  {/* {JSON.stringify({
                    isOverflowFlag: isOverflowFlag.value,
                    isOverflow: isOverflow.value,
                  })} */}

                  {/* {selectedGroupField.value.caption &&
                    (isOverflow.value || isOverflowFlag.value) && ( */}
                  {quickGroupMoreShow.value && (
                    <span
                      onClick={() => {
                        isOverflowFlag.value = !isOverflowFlag.value;
                      }}
                    >
                      <TIcon
                        class={[
                          'cursor-pointer',
                          isOverflowFlag.value && 'rotate-180',
                        ]}
                        style='font-size: 10px;'
                        name={`${TComponents?.IconList?.common ?? 'fas dx-icon'} ${TComponents?.IconList?.arrowDown ?? 'icon-t-arrow-down'}`}
                        // name={
                        //   isOverflowFlag.value
                        //     ? 'fas dx-icon icon-teld-arrow-up-thin'
                        //     : 'fas dx-icon icon-teld-arrow-bottom-thin'
                        // }
                      />
                    </span>
                  )}
                </div>
              </div>
              <div
                ref={refQuickGroupDiv}
                style={{
                  position: 'relative',
                  overflow: 'hidden',
                  marginRight: '20px',
                  maxHeight: isOverflowFlag.value ? 'fit-content' : '56px',
                }}
              >
                <TQuickFilter
                  ref={refQuickFilter}
                  {...dynamicProps}
                  {...quickFilterEvent}
                  // isPcOnly={true}
                  showTotalCount={mappingProps.showGroupingTotalCount}
                  optColumns={props.optColumns}
                  loading={mappingProps.loading}
                  onFilterChanged={onFilterChangedHandler}
                  filterFields={filterFields.value}
                  // Mock
                  quickItems={quickItems.value}
                  quickItemSummary={quickItemSummary.value}
                  onInit={onGroupInitHandler}
                  onQuerySummary={onGroupSummaryHandler}
                  // Mock
                ></TQuickFilter>
              </div>
            </div>
          )}
        </>
      );
    };
    const onFilterChangedHandler = () => {
      emit('groupChanged');
      console.log('onFilterChangedHandler');
      execQuery();
    };

    const quickItems = ref({});
    const quickItemSummary = ref({});
    const filterField = ref({
      // ID: '2d79b143-8e01-4524-bb26-848b74b4159b',
      // tableAlias: 'OrderType',
      // tableCode: 'OrderType',
      // tableName: '订单类型标识',
      // fieldCode: 'OrderType',
      // fieldName: '订单类型标识',
      // fieldAlias: 'OrderType',
      displayType: 'tab',
      mockDataModel: 'default',
      isMultiple: false /** 现在后端引擎不知道null的 in 操作 */,
      enableStatistics: true,
      hideEmpty: false,
      showTitle: false, // showTitle: true,
      enableAllItem: mappingProps.enableGroupingAllItem,
      valueType: 'sdo',
      filter_isMultiple: false,
      filter_dataValue: '',
    });
    watch(
      () => mappingProps.enableGroupingAllItem,
      val => {
        filterField.value.enableAllItem =
          val && quickItemSummary.value.length > 1;
      },
    );
    const filterFields = computed(() => {
      let returnValue = [];
      if (filterField.value.fieldAlias) {
        returnValue.push(filterField.value);
      }
      return returnValue;
      // return [
      //   // {
      //   //   ID: '9af52b9a-981d-46b0-a5f0-6b2b37a94318',
      //   //   tableAlias: 'IfGift',
      //   //   tableCode: 'IfGift',
      //   //   tableName: '是否参加活动标识',
      //   //   fieldCode: 'IfGift',
      //   //   fieldName: '是否参加活动标识',
      //   //   fieldAlias: 'IfGift',
      //   //   displayType: 'tab',
      //   //   mockDataModel: 'default',
      //   //   isMultiple: false,
      //   //   enableStatistics: false,
      //   //   hideEmpty: false,
      //   //   showTitle: true,
      //   //   enableAllItem: false,
      //   //   valueType: 'boolean',
      //   //   filter_isMultiple: false,
      //   // },
      //   // {
      //   //   ID: '2d79b143-8e01-4524-bb26-848b74b4159b',
      //   //   tableAlias: 'OrderType',
      //   //   tableCode: 'OrderType',
      //   //   tableName: '订单类型标识',
      //   //   fieldCode: 'OrderType',
      //   //   fieldName: '订单类型标识',
      //   //   fieldAlias: 'OrderType',
      //   //   displayType: 'tab',
      //   //   mockDataModel: 'default',
      //   //   isMultiple: false,
      //   //   enableStatistics: true,
      //   //   hideEmpty: false,
      //   //   showTitle: false, // showTitle: true,
      //   //   enableAllItem: false,
      //   //   valueType: 'sdo',
      //   //   filter_isMultiple: false,
      //   //   filter_dataValue:
      //   //     '{"DataBind":"DataQuery.GetSDO_OrderTypeBasicList(DefaultInputFilter,PageIndex,PageSize,AdvancedFilter,AdvancedSort).List","DataSource":"e5991898-f5e2-4aef-b485-d2ad33145e25","ActionType":3,"RelatedCdoCode":"GetSDO_OrderTypeBasicList","ServicePara":[{"ID":"1878b748-8818-4fa3-96ed-5b60eb9c4d1b","Code":"DefaultInputFilter","Name":"模糊匹配参数","DataType":9,"IsEmpty":0,"Value":""},{"ID":"51d4b99e-4eda-47a5-885a-42ebfaae8805","Code":"PageIndex","Name":"页码","DataType":2,"IsEmpty":0,"Value":""},{"ID":"8ac6d154-9b74-4d4a-a00a-43c25b7729ed","Code":"PageSize","Name":"分页大小","DataType":2,"IsEmpty":0,"Value":""},{"ID":"ae6f5a6e-c6b5-47aa-848c-edf92a4568c0","Code":"AdvancedFilter","Name":"高级查询过滤条件","DataType":9,"IsEmpty":0,"Value":""},{"ID":"6f463bc9-31e7-41f4-8bca-2f4358d34d93","Code":"AdvancedSort","Name":"高级查询排序条件","DataType":9,"IsEmpty":0,"Value":""}],"isMultiple":false,"labelField":"Name","valueField":"Code","columns":[{"ID":"Code","dataField":"Code","caption":"编号","dataType":"Int"},{"ID":"Name","dataField":"Name","caption":"名称","dataType":"String"}],"ServiceParam":[{"ID":"1878b748-8818-4fa3-96ed-5b60eb9c4d1b","Code":"DefaultInputFilter","Name":"模糊匹配参数","DataType":9,"IsEmpty":0,"Value":""},{"ID":"51d4b99e-4eda-47a5-885a-42ebfaae8805","Code":"PageIndex","Name":"页码","DataType":2,"IsEmpty":0,"Value":""},{"ID":"8ac6d154-9b74-4d4a-a00a-43c25b7729ed","Code":"PageSize","Name":"分页大小","DataType":2,"IsEmpty":0,"Value":""},{"ID":"ae6f5a6e-c6b5-47aa-848c-edf92a4568c0","Code":"AdvancedFilter","Name":"高级查询过滤条件","DataType":9,"IsEmpty":0,"Value":""},{"ID":"6f463bc9-31e7-41f4-8bca-2f4358d34d93","Code":"AdvancedSort","Name":"高级查询排序条件","DataType":9,"IsEmpty":0,"Value":""}]}',
      //   // },
      //   filterField.value,
      // ];
    });

    const onGroupInitHandler = () => {
      // alert(1);
      debugger;

      _.each(filterFields.value, f => {
        onGroupSummaryHandler({
          summaryGroupColumnStatement: {
            ExtSetting: {
              GroupColumns: [
                {
                  Code: `${f.tableCode}.${f.fieldCode}`,
                },
              ],
            },
          },
        });
      });
    };

    const onGroupSummaryHandler = groupColumn => {
      console.log('onGroupSummaryHandler', groupColumn);
      let mockSummary = refQuickFilter.value.mockSummary;
      let col =
        groupColumn?.summaryGroupColumnStatement?.ExtSetting?.GroupColumns[0]
          ?.Code;
      col = _.last(col.split('.'));

      nextTick(() => {
        mappingProps.loading = true;
        emit('groupSummary', { groupColumn: col });
      });
    };

    const mappingColumns = computed(() => {
      return _.transform(
        columns.value,
        (result, value, key) => {
          result[value.field] = value;
        },
        {},
      );
    });

    const getColValue = (col, value) => {
      let returnValue = value;
      let column = _.find(columns.value, { field: col });
      if (
        column &&
        column.optCol &&
        column.optCol.enumDisp &&
        column.optCol.enumDisp.valMapping &&
        column.optCol.enumDisp.enumRanges &&
        column.optCol.enumDisp.enumRanges.length > 0
      ) {
        let item = _.find(column.optCol.enumDisp.enumRanges, eachItem => {
          return eachItem.val == value;
        });
        if (item) {
          returnValue = item.text;
          if (item.ValueInfo_text) {
            returnValue = t(item.ValueInfo_text, item.text || '');
          }
        }
      }
      return returnValue;
    };

    // const sortQuickItems = computed(() => {
    //   return _.orderBy(quickItems.value[]);
    // });
    watch(
      () => [mappingProps.groupItemSummary, selectedGroupFieldSort.value],
      newValue => {
        const [itemSummary, filedSort] = newValue;
        // alert(1111)
        debugger;
        mappingProps.loading = false;
        console.log(itemSummary);
        let groupColumn = _.first(
          _.filter(_.keys(_.first(itemSummary)), c => c != 'Total'),
        );

        quickItemSummary.value = itemSummary;

        filterField.value.enableAllItem =
          mappingProps.enableGroupingAllItem &&
          quickItemSummary.value.length > 1;

        const notNullItems = _.filter(
          itemSummary,
          o => !_.isNil(o[groupColumn]),
        );

        let quickItemsValue = itemSummary.map(col => ({
          label:
            null === col[groupColumn]
              ? $q.lang.dataGrid?.groupNullText
              : getColValue(groupColumn, col[groupColumn]),
          value: col[groupColumn],
        }));

        switch (filedSort) {
          case 'CA':
          case 'CD':
            const mapping = _.zipObject(
              _.map(quickItemsValue, 'value'),
              _.values(quickItemsValue),
            );
            const s = _.orderBy(itemSummary, ...sortMapping[filedSort]).map(
              o => mapping[o[groupColumn]],
            );
            quickItemsValue = s;
            break;
          case 'NA':
          case 'ND':
            quickItemsValue = _.orderBy(
              quickItemsValue,
              ...sortMapping[filedSort],
            );
            break;
        }
        quickItemsValue = _.orderBy(quickItemsValue, ...sortMapping[filedSort]);

        quickItems.value = {
          [groupColumn]: quickItemsValue,
        };

        nextTick(() => {
          if (groupColumn) {
            refQuickFilter.value.setSelectedItem({
              // [groupColumn]: _.first(itemSummary)[groupColumn],
              [groupColumn]: _.first(quickItemsValue).value,
            });
          }
          nextTick(() => {
            execQuery();
            refreshHeightWithQuickGroup();
          });
        });
      },
    );

    const currentPage = ref(computedPagination.value.page);
    const maxPage = computed(() => {
      // return Math.ceil(props.rowsNumber / props.pageSize);
      return Math.ceil(
        computedPagination.value.rowsNumber /
          computedPagination.value.rowsPerPage,
      );
    });
    watch(
      () => computedPagination.value.page,
      page => {
        currentPage.value = page;
      },
    );
    watch(
      () => currentPage.value,
      page => {
        if (computedPagination.value.page != page) {
          emit('request', {
            pagination: { ...computedPagination.value, page: page },
            filter: '',
            getCellValue,
          });
        }
      },
    );

    watch(
      () => mappingProps.loading,
      val => {
        if (false === val) {
          scrollHover();
        }
      },
    );

    const renderSimplePagination = () => {
      return (
        <div
          class='simplePaging q-table__bottom row items-center justify-center'
          style='background-color: white;'
        >
          {wrapRows.value.length > 0 && (
            <TPagination
              v-model={currentPage.value}
              // v-model={computedPagination.value.page}
              input
              input-style='color:rgba(0,0,0,0.8)'
              icon-first='none'
              icon-last='none'
              max-pages='3'
              direction-links
              max={maxPage.value}
            />
          )}
        </div>
      );
    };

    function renderPrefabPagination() {
      return (
        <>
          {mappingProps.simplePaging
            ? renderPagination(C_Prefab.Simple)
            : renderPagination(
                isDesktop.value ? C_Prefab.Perfective : C_Prefab.Mobile,
              )}
          {/* {renderPagination()}
          {renderPagination(C_Prefab.Simple)} */}
        </>
      );
    }

    function renderPagination(prefab = C_Prefab.Perfective) {
      return (
        <div
          class={[
            prefab != C_Prefab.Mobile
              ? 'q-table__bottom'
              : 'table__bottom_marginTop10',
            'row items-center',
            prefab === C_Prefab.Simple ? 'justify-center' : 'justify-end',
          ]}
          style='background-color: white; border-top-color: transparent;'
        >
          {wrapRows.value.length > 0 && (
            <TPrefabPagination
              v-model={currentPage.value}
              prefab={prefab}
              max={maxPage.value}
              pageSizeRange={pageSizeRange.value}
              totals={props.isDev ? 10 : computedPagination.value.rowsNumber}
              v-model:pageSize={mappingProps.pageSize}
              onPageChanged={page => {
                // execQuery();
                mappingExpose.pageIndex.value = page;
              }}
              onPageSizeChanged={pageSize => {
                execQuery();
              }}
            />
          )}
        </div>
      );
    }

    const scrollLeft = ref(0);
    const refHeader = ref(null);
    let refHeaderScroll = null;
    function onScrollHandler(e) {
      scrollLeft.value = e.target.scrollLeft;

      if (!refHeaderScroll) {
        if (refHeader.value) {
          refHeaderScroll = refHeader.value.querySelector('.scroll');
        }
      }
      if (refHeaderScroll) refHeaderScroll.scrollLeft = scrollLeft.value;

      console.log('details', e);
    }

    const isIntersecting = ref(true);
    const isIntersectingVisable = ref(true);
    const showHeader = computed(() => {
      refHeaderScroll = null;
      return false === isIntersecting.value && isIntersectingVisable.value;
    });

    function onIntersection(entry) {
      isIntersecting.value = entry.isIntersecting;
    }
    function syncScrollPosition(target, root) {
      let selector = '.scroll';
      let headerScroll = target.querySelector(selector);
      let rootScroll = root.querySelector(`.t-data-grid--main ${selector}`);

      headerScroll.scrollLeft = rootScroll.scrollLeft;
    }

    function refreshHeaderScrollPosition(target, root) {
      // /** OK */
      // setTimeout(() => {
      //   root.querySelector('.t-data-grid--main .scroll').dispatchEvent(
      //     new Event('scroll', {
      //       bubbles: true, // 是否冒泡
      //       cancelable: true, // 是否可以取消
      //     }),
      //   );
      // });

      /** OK */
      setTimeout(() => {
        let selector = '.scroll';
        let headerScroll = target.querySelector(selector);
        if (headerScroll) {
          headerScroll.scrollLeft = scrollLeft.value;
        } else {
          syncScrollPosition(target, root);
        }
      });

      // /** OK */
      // setTimeout(() => {
      //   syncScrollPosition(target, root);
      // });
    }

    function refreshHeaderLayout(target, root) {
      const thSelector = 'table > thead > tr > th';
      let ths = target.querySelectorAll(thSelector);
      let rootThs = root.querySelectorAll(`.t-data-grid--main ${thSelector}`);

      refreshHeaderScrollPosition(target, root);

      if (0 === ths.length || 0 === rootThs.length) {
        return;
      }
      const { height, width, style, css } = dom;

      for (var i = 0; i < ths.length; i++) {
        let th = ths[i];
        let rootTh = rootThs[i];
        if (rootTh && th.dataset?.field === rootTh.dataset?.field) {
          const w = style(rootTh, 'width');
          const wTh = style(th, 'width');
          if (w !== wTh) css(th, { width: w, minWidth: w, maxWidth: w });
        }
      }
    }
    function onIntersectionWithHeader(entry) {
      if (entry.isIntersecting) {
        refreshHeaderLayout(entry.target, refRoot.value);
        setFixedColumn()
      }
    }
    const refHeaderWidth = ref(0);
    function onResize(size) {
      refHeaderWidth.value = size.width;
    }

    const isDynamicFillMode = computed(
      () => 'dynamic' === mappingProps.fillMode,
    );

    function rootIntersectionHandler(entry) {
      isIntersectingVisable.value = entry.isIntersecting;
      if (false === isIntersecting.value) {
        let { bottom } = entry.boundingClientRect;
        bottom -= mappingProps.fixedHeaderOffsetTop;
        if (bottom < 90) {
          isIntersectingVisable.value = false;
          refHeaderScroll = null;
        }
      }
    }

    function calculateTableHeaderSpans(data) {
      const header = [];
      let maxDepth = 0;

      // 递归计算 colspan 和深度
      function calculateSpans(items, depth) {
        maxDepth = Math.max(maxDepth, depth);
        return items.map(item => {
          const headerItem = { label: item.label, depth };
          if (item.children && item.children.length > 0) {
            const childSpans = calculateSpans(item.children, depth + 1);
            headerItem.children = childSpans;
            headerItem.colspan = childSpans.reduce(
              (total, child) => total + (child.colspan || 1),
              0,
            );
          } else {
            // header.push(item.dataIndex);
          }
          if (item.dataField) {
            headerItem.dataIndex = item.dataField;
            header.push(item.dataField);
          }
          return headerItem;
        });
      }

      // 计算 rowspan
      function calculateRowspans(items, depth) {
        items.forEach(item => {
          if (item.children) {
            calculateRowspans(item.children, depth + 1);
            item.rowspan = 1;
          } else {
            item.rowspan = maxDepth - depth + 1;
          }
        });
      }

      const headerWithSpans = calculateSpans(data, 1);
      calculateRowspans(headerWithSpans, 1);
      return { headerWithSpans, maxDepth, header };
    }

    const computedHeaders = computed(() => {
      let headers = mappingProps.headers;
      let { headerWithSpans, maxDepth, header } =
        calculateTableHeaderSpans(headers);
      return { headerWithSpans, maxDepth, header };
    });

    const isMultiMeader = computed(() => {
      return mappingProps.headers.length > 0;
    });

    function renderHeaderCells(
      props,
      headers,
      level,
      maxHeaderLevel,
      currentLevel = 0,
    ) {
      return headers.map((header, index) => {
        let isLast = index == headers.length - 1;
        const thProps = {
          attrs: {
            class: `mulit-header-span ${isLast ? 'last' : ''}`,
          },
          key: header.label,
        };

        if (header.colspan) {
          thProps.attrs.colspan = header.colspan;
        }
        if (header.rowspan /*&& currentLevel === 0*/) {
          thProps.attrs.rowspan = header.rowspan;
        }

        let th = (
          <TTh
            style={{
              '--t-header-sticky-top': `${currentLevel * 48}px`,
            }}
            class={['sticky']}
            {...thProps.attrs}
          >
            {header.label}
          </TTh>
        );
        if (header.dataIndex) {
          const col = props.colsMap[header.dataIndex];
          th = headerCellSlot(
            {
              ...props,
              col: col,
            },
            {
              style: {
                '--t-header-sticky-top': `${currentLevel * 48}px`,
              },
              rowSpan: header.rowspan,
              class: `mulit-header-field ${col?.fixedColumn==="left" && 'sticky'} ${isLast ? 'last' : ''}`,
            },
          );
        }

        if (header.children && currentLevel < level) {
          return renderHeaderCells(
            props,
            header.children,
            level,
            maxHeaderLevel,
            currentLevel + 1,
          );
        } else if (currentLevel === level) {
          return th;
        }

        return null;
      });
    }

    const allSelected = computed({
      get: () =>
        selected.value.length === 0
          ? false
          : selected.value.length === wrapRows.value.length
            ? true
            : null,
      set: val => {
        if (val === null) return;
        if (val) {
          selected.value = wrapRows.value.slice();
        } else {
          selected.value = [];
        }
      },
    });

    function renderCheckAll(props) {
      return (
        <TCheckbox
          v-model={allSelected.value}
          // modelValue={allSelected.value}
          // onUpdate:modelValue={val => {
          //   if (val) {
          //     selected.value = wrapRows.value.slice();
          //   } else {
          //     selected.value = [];
          //   }
          // }}
        />
      );
    }
    function renderHeaders(props) {
      let {
        headerWithSpans: headers,
        maxDepth: headerLevel,
        header,
      } = computedHeaders.value;

      debugger;
      const headerRows = [];
      for (let i = 0; i < headerLevel; i++) {
        headerRows.push(
          <TTr key={i} class={['t-datagrid-mulit-header']} props={props}>
            {0 == i && 'none' != mappingProps.selection && (
              // headerCellRowNumber(props.colsMap.rowNumberColumn, {
              //   rowSpan: headerLevel,
              //   // style: 'z-index: 116 !important;',
              //   class:
              //     'mulit-header_row-number fixed-column-left fixed-column-left-shadow',
              // })
              <TTh
                rowSpan={headerLevel}
                class='q-table--col-auto-width mulit-header_checkbox'
                props={props}
              >
                <div class='selectionBox'>
                  {'multiple' === mappingProps.selection &&
                    renderCheckAll(props)}
                </div>
              </TTh>
            )}
            {0 == i &&
              mappingProps.showRowNumber &&
              headerCellRowNumber(props.colsMap.rowNumberColumn, {
                rowSpan: headerLevel,
                // style: 'z-index: 116 !important;',
                class: `mulit-header_row-number fixed-column-left fixed-column-left-shadow ${'none' != mappingProps.selection && 'left50px'}`,
              })}
            {0 == i &&
              mappingProps.enableCmdCol &&
              stickyCmdColumn.value &&
              stickyCmdColumn.value.fixedPosition != 'right' &&
              headerCellSlot(
                {
                  ...props,
                  col: props.colsMap.stickyCmdColumn,
                },
                {
                  rowSpan: headerLevel,
                  class: 'mulit-header_cmd',
                },
              )}
            {renderHeaderCells(props, headers, i, headerLevel)}
            {0 == i &&
              mappingProps.enableCmdCol &&
              stickyCmdColumn.value &&
              stickyCmdColumn.value.fixedPosition == 'right' &&
              // <TTh rowSpan={headerLevel}>操作</TTh>
              headerCellSlot(
                {
                  ...props,
                  col: props.colsMap.stickyCmdColumn,
                },
                {
                  rowSpan: headerLevel,
                  class: 'mulit-header_cmd',
                },
              )}
          </TTr>,
        );
      }

      return headerRows;
    }

    function calculateHeaderLevel(headers) {
      let maxLevel = 1;
      headers.forEach(header => {
        if (header.children) {
          maxLevel = Math.max(
            maxLevel,
            calculateHeaderLevel(header.children) + 1,
          );
        }
      });
      return maxLevel;
    }

    return () => {
      const thresholds = [];
      for (let i = 0; i <= 1.0; i += 0.01) {
        thresholds.push(i);
      }

      const intersectionCfg = {
        root: document,
        rootMargin: `-${mappingProps.fixedHeaderOffsetTop}px 0px 0px 0px`,
      };

      return (
        <div
          ref={refRoot}
          style={{
            '--t-fixed-header-offset-top': `${mappingProps.fixedHeaderOffsetTop}px`,
            '--t-fixed-header-padding': mappingProps.fixedHeaderPadding,
            '--t-fixed-header-padding-top': `${mappingProps.fixedHeaderPaddingTop}px`,
            '--t-fixed-header-zindex': mappingProps.fixedHeaderZindex,
            '--t-fixed-header-bg-color':
              mappingProps.fixedHeaderBackgroundColor,
            [!mappingProps.showFixedShadow &&
            '--t-fixed-box-shadow-left-width']:
              `${isDesktop.value ? 0 : '8px'}`,
            [mappingProps.showFixedShadow &&
            '--t-fixed-box-shadow-left-border-right-width']: '0',
            '--t-scroll-padding-left': `${mappingProps.paddingLeft}px`,
            '--t-left-fixed-left': `${0 - mappingProps.paddingLeft}px`,
          }}
          class={[
            't-datagrid-container',
            props.isDev && 't-datagrid-container-dev',
          ]}
          onMouseleave={e => {
            mouseUp(e, true);
          }}
          onMouseup={e => {
            mouseUp(e, true);
          }}
          v-intersection={{
            handler: rootIntersectionHandler,
            cfg: {
              ...intersectionCfg,
              threshold: thresholds,
            },
          }}
        >
          {showFixedHeader.value && (
            <>
              <span
                v-intersection={{
                  handler: onIntersection,
                  cfg: intersectionCfg,
                }}
              ></span>
              <QResizeObserver onResize={onResize} />
            </>
          )}
          {false && debuggerInfo()}
          {/* {JSON.stringify(`${quickGroupHeight.value} ${h.value} ${height.value}`)} */}
          {isDesktop.value && renderQuickFilter()}
          <TTable
            onVirtualScroll={() => {
              setFixedColumnByMousemove();
            }}
            onMousemove={setFixedColumnByMousemove}
            onRowClick={onRowClickHandler}
            onUpdate:selected={onSelectionHandler}
            // onRowContextmenu={onRowContextmenu}
            ref={refComponent}
            style={computedStyle.value}
            {...attrs}
            {...pickOwnForBasicComponent(mappingProps, TTable.props, attrs)}
            class={[
              't-data-grid',
              't-data-grid--main',
              'scrollbar-hover-visible',
              styles.module,
              !props.disableFixedColumn &&
                props.selection != 'none' &&
                'selection',
              props.selection != 'none' && 'enableSelection',
              mappingProps.enableCmdCol && 'stickyCol',
              mappingProps.allowColumnResizing && 'allowColumnResizing',
              mappingProps.allowColumnWarp && 'white-space-wrap',
              isDynamicFillMode.value && 'dynamic-height',
              // (classGridSimple.value.showStriped) && 'striped'
            ]}
            v-show={mappingProps.visible}
            // rows={mappingProps.isDev ? mockRows.value : computedRows.value}
            rows={wrapRows.value}
            // rows={mappingProps.isDev ? mockRows.value : computedRows.value}
            {...mOpts.value}
            // pagination={mOpts.value.pagination} /** 不能这样会影响分页 */
            // columns={columns.value}
            // visibleColumns={
            //   mappingProps.isDev
            //     ? columns.value
            //         .filter(item => item.__isShow)
            //         .map(item => item.name)
            //     : mOpts.value.visibleColumns
            // }
            // columns={wrapColumns.value}
            columns={[
              mappingProps.showRowNumber && rowNumberColumn.value,
              mappingProps.enableCmdCol &&
                stickyCmdColumn.value &&
                stickyCmdColumn.value.fixedPosition != 'right' &&
                stickyCmdColumn.value,
              ...wrapColumns.value,
              mappingProps.enableCmdCol &&
                stickyCmdColumn.value &&
                stickyCmdColumn.value.fixedPosition == 'right' &&
                stickyCmdColumn.value,
            ].filter(item => item)}
            visibleColumns={wrapVisibleColumns.value}
            hide-pagination={
              mappingProps.hidePagination ||
              (false === mappingProps.hidePagination &&
                mappingProps.simplePaging) ||
              (false === mappingProps.hidePagination &&
                C.UNSET == mappingProps.paginationStyle)
            }
            v-model:pagination={computedPagination.value}
            v-model:selected={selected.value}
            onRequest={onRequest}
            virtual-scroll
            dense={false}
            binary-state-sort={false}
            rows-per-page-options={pageSizeRange.value}
            square
            flat
            {...classGridSimple.value}
            wrap-cells
            hide-no-data
            hide-selected-banner={true}
          >
            {{
              'header-selection': scope => (
                <div class='selectionBox'>
                  <TCheckbox tabindex='1' v-model={scope.selected} />
                </div>
              ),
              'body-selection': bodySelection,
              'top-row': slotTopRow,
              'body-cell': rowData => {
                return (
                  <TTd props={rowData}>
                    {rowData.value}
                    {props.menuModel ? contextMenuList(rowData) : null}
                  </TTd>
                );
              },
              // ...slots,
              ...cellSlot,
              'body-cell-stickyCmdColumn': bodyCellCmd,
              'body-cell-rowNumberColumn': bodyCellRowNumber,
              'header-cell-rowNumberColumn': headerCellRowNumber,
              [isMultiMeader.value && 'header']: props => {
                return renderHeaders(props);
              },
              'header-cell': props.isDev ? null : headerCellSlot,
              'loading': () => {
                return (
                  <QInnerLoading
                    style='z-index: 120;color: var(--t-color);  opacity: 65%;'
                    style={{
                      zIndex: 120,
                      color: 'var(--t-color)',
                      opacity: '65%',
                      ...(isDynamicFillMode.value &&
                        mappingProps.dynamicFullLoading && {
                          position: 'fixed',
                        }),
                    }}
                    showing
                  />
                );
              },
              // ...headerCell(),
              // 'header-cell':
              //   !props.isDev &&
              //   (),
              // pagination: paginationSlot
            }}
          </TTable>
          <transition>
            {wrapRows.value.length > 0 && showFixedHeader.value && (
              <div
                v-show={showHeader.value}
                ref={refHeader}
                v-intersection={{
                  handler: onIntersectionWithHeader,
                  cfg: {
                    root: intersectionCfg.root,
                  },
                }}
                class={['t-fixed-header']}
                style={{
                  // opacity: showHeader.value ? 1 : 0,
                  // [false === showHeader.value && 'top']: '-100%',
                  // [false === showHeader.value && 'zIndex']: '0',
                  width: `${refHeaderWidth.value}px`,
                }}
              >
                <div transition='slide-down'>
                  <TTable
                    onMousemove={setFixedColumnByMousemove}
                    onRowClick={onRowClickHandler}
                    {...attrs}
                    {...pickOwnForBasicComponent(
                      mappingProps,
                      TTable.props,
                      attrs,
                    )}
                    style='max-height: unset;'
                    class={[
                      't-data-grid',
                      'scrollbar-hover-visible',
                      styles.module,
                      !props.disableFixedColumn &&
                        props.selection != 'none' &&
                        'selection',
                      props.selection != 'none' && 'enableSelection',
                      mappingProps.enableCmdCol && 'stickyCol',
                      mappingProps.allowColumnResizing && 'allowColumnResizing',
                      mappingProps.allowColumnWarp && 'white-space-wrap',
                      isDynamicFillMode.value && 'dynamic-height',
                      // /**控制是否固定式也先四行顾虑*/showAutoFilterRow.value && 'auto-filter-row',
                    ]}
                    v-show={mappingProps.visible}
                    {...mOpts.value}
                    columns={[
                      mappingProps.showRowNumber && rowNumberColumn.value,
                      mappingProps.enableCmdCol &&
                        stickyCmdColumn.value &&
                        stickyCmdColumn.value.fixedPosition != 'right' &&
                        stickyCmdColumn.value,
                      ...wrapColumns.value,
                      mappingProps.enableCmdCol &&
                        stickyCmdColumn.value &&
                        stickyCmdColumn.value.fixedPosition == 'right' &&
                        stickyCmdColumn.value,
                    ].filter(item => item)}
                    visibleColumns={wrapVisibleColumns.value}
                    hide-pagination={true}
                    // v-model:pagination={computedPagination.value}
                    // v-model:selected={selected.value}
                    // onRequest={onRequest}
                    // virtual-scroll
                    dense={false}
                    binary-state-sort={false}
                    rows-per-page-options={[1]}
                    rows={[]}
                    square
                    flat
                    // {...classGridSimple.value}
                    wrap-cells
                    hide-no-data
                    hide-selected-banner={true}
                  >
                    {{
                      'header-selection': scope =>
                        'multiple' === mappingProps.selection &&
                        renderCheckAll(scope),
                      'body-selection': bodySelection,
                      'top-row': slotTopRow,
                      'body-cell': rowData => {
                        return (
                          <TTd props={rowData}>
                            {rowData.value}
                            {props.menuModel ? contextMenuList(rowData) : null}
                          </TTd>
                        );
                      },
                      // ...slots,
                      ...cellSlot,
                      'body-cell-stickyCmdColumn': bodyCellCmd,
                      'body-cell-rowNumberColumn': bodyCellRowNumber,
                      'header-cell-rowNumberColumn': headerCellRowNumber,
                      [isMultiMeader.value && 'header']: props => {
                        return renderHeaders(props);
                      },
                      'header-cell': props.isDev ? null : headerCellSlot,
                      'loading': () => {
                        /** 这个代码对于显示浮动表头时的加载宽度有用 */
                      },
                    }}
                  </TTable>
                </div>
              </div>
            )}
          </transition>
          {false === props.hidePagination &&
            mappingProps.visible &&
            // C.UNSET !== mappingProps.paginationStyle &&
            renderPrefabPagination()}
          {wrapRows.value.length == 0 && mappingProps.visible && (
            <div
              style={[
                'position: absolute; inset: 0px;display: flex;justify-content: center;align-items: center; margin: auto; width: 150px; height: 150px;',
                isDynamicFillMode.value &&
                  mappingProps.dynamicMinHeight <= 330 &&
                  showAutoFilterRow.value &&
                  'padding-top: 64px;',
              ]}
            >
              <NoDataPlaceholder
                text={$q.lang.dataGrid?.emptyText}
              ></NoDataPlaceholder>
            </div>
          )}
          {twoWayProps.showPopupColumnsSetting.value &&
            renderPopupColumnSetting()}
        </div>
      );
    };
  },
});
